summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp4
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java101
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java22
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java6
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java11
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java110
-rw-r--r--apex/media/framework/java/android/media/MediaParser.java62
-rw-r--r--apex/statsd/framework/Android.bp25
-rw-r--r--apex/statsd/framework/test/Android.bp36
-rw-r--r--apex/statsd/framework/test/AndroidTest.xml34
-rw-r--r--cmds/statsd/src/atoms.proto130
-rw-r--r--cmds/statsd/src/external/StatsPuller.cpp15
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.cpp29
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.h11
-rw-r--r--cmds/statsd/src/stats_log.proto5
-rw-r--r--cmds/statsd/src/stats_log_util.cpp17
-rw-r--r--cmds/statsd/src/stats_log_util.h3
-rw-r--r--cmds/statsd/tests/guardrail/StatsdStats_test.cpp9
-rw-r--r--core/java/android/app/ActivityTaskManager.java14
-rw-r--r--core/java/android/app/AppOpsManager.java11
-rw-r--r--core/java/android/app/TaskInfo.java18
-rw-r--r--core/java/android/app/admin/DevicePolicyCache.java8
-rw-r--r--core/java/android/companion/BluetoothDeviceFilterUtils.java7
-rw-r--r--core/java/android/companion/BluetoothLeDeviceFilter.java14
-rw-r--r--core/java/android/content/Intent.java2
-rw-r--r--core/java/android/content/pm/PackageParser.java6
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageUtils.java6
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java42
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java208
-rw-r--r--core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java73
-rw-r--r--core/java/android/hardware/camera2/impl/CaptureResultExtras.java28
-rw-r--r--core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java37
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java5
-rw-r--r--core/java/android/net/DhcpResults.java3
-rw-r--r--core/java/android/net/DnsPacket.java235
-rw-r--r--core/java/android/net/DnsResolver.java15
-rw-r--r--core/java/android/net/NetworkUtils.java11
-rw-r--r--core/java/android/net/StaticIpConfiguration.java2
-rw-r--r--core/java/android/net/shared/Inet4AddressUtils.java166
-rw-r--r--core/java/android/net/shared/InetAddressUtils.java58
-rw-r--r--core/java/android/os/CarrierAssociatedAppEntry.aidl19
-rw-r--r--core/java/android/os/CarrierAssociatedAppEntry.java68
-rw-r--r--core/java/android/os/ISystemConfig.aidl5
-rw-r--r--core/java/android/os/Process.java7
-rw-r--r--core/java/android/os/SystemConfigManager.java25
-rw-r--r--core/java/android/os/Users.md80
-rw-r--r--core/java/android/permission/Permissions.md6
-rwxr-xr-xcore/java/android/provider/Settings.java7
-rw-r--r--core/java/android/service/autofill/InlineSuggestionRenderService.java31
-rw-r--r--core/java/android/service/autofill/augmented/AugmentedAutofillService.java4
-rw-r--r--core/java/android/service/autofill/augmented/FillCallback.java21
-rw-r--r--core/java/android/service/autofill/augmented/FillWindow.java26
-rw-r--r--core/java/android/service/autofill/augmented/IFillCallback.aidl4
-rw-r--r--core/java/android/service/controls/Control.java7
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java3
-rw-r--r--core/java/android/util/FeatureFlagUtils.java1
-rw-r--r--core/java/android/util/apk/ApkSigningBlockUtils.java1
-rw-r--r--core/java/android/util/apk/SourceStampVerifier.java229
-rw-r--r--core/java/android/util/apk/TEST_MAPPING12
-rw-r--r--core/java/android/view/InsetsController.java12
-rw-r--r--core/java/android/view/InsetsState.java106
-rw-r--r--core/java/android/view/SurfaceControl.java31
-rw-r--r--core/java/android/view/SurfaceView.java2
-rw-r--r--core/java/android/view/SyncRtSurfaceTransactionApplier.java12
-rw-r--r--core/java/android/view/ViewRootImpl.java3
-rw-r--r--core/java/android/view/ViewRootInsetsControllerHost.java5
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java72
-rw-r--r--core/java/android/widget/ToastPresenter.java3
-rw-r--r--core/java/android/widget/inline/InlineContentView.java14
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java31
-rw-r--r--core/java/com/android/internal/app/ChooserListAdapter.java64
-rw-r--r--core/java/com/android/internal/app/ResolverListAdapter.java22
-rw-r--r--core/java/com/android/internal/os/FuseAppLoop.java18
-rw-r--r--core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java2
-rw-r--r--core/java/com/android/internal/os/Zygote.java13
-rw-r--r--core/java/com/android/internal/policy/BackdropFrameRenderer.java46
-rw-r--r--core/java/com/android/internal/policy/DecorView.java59
-rw-r--r--core/java/com/android/internal/policy/DividerSnapAlgorithm.java11
-rw-r--r--core/java/com/android/internal/widget/ConversationLayout.java11
-rw-r--r--core/java/com/android/internal/widget/MessagingGroup.java10
-rw-r--r--core/java/com/android/internal/widget/MessagingLinearLayout.java21
-rw-r--r--core/java/com/android/server/SystemConfig.java29
-rw-r--r--core/jni/android_net_NetUtils.cpp8
-rw-r--r--core/jni/android_view_SurfaceControl.cpp14
-rw-r--r--core/proto/android/stats/connectivity/Android.bp14
-rw-r--r--core/proto/android/stats/connectivity/tethering.proto97
-rw-r--r--core/res/res/drawable-car-night/car_dialog_button_background.xml32
-rw-r--r--core/res/res/drawable-car/car_dialog_button_background.xml20
-rw-r--r--core/res/res/layout/notification_template_messaging_group.xml1
-rw-r--r--core/res/res/values-af/strings.xml5
-rw-r--r--core/res/res/values-am/strings.xml1
-rw-r--r--core/res/res/values-ar/strings.xml7
-rw-r--r--core/res/res/values-as/strings.xml5
-rw-r--r--core/res/res/values-az/strings.xml1
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml1
-rw-r--r--core/res/res/values-be/strings.xml1
-rw-r--r--core/res/res/values-bg/strings.xml3
-rw-r--r--core/res/res/values-bn/strings.xml5
-rw-r--r--core/res/res/values-bs/strings.xml9
-rw-r--r--core/res/res/values-ca/strings.xml5
-rw-r--r--core/res/res/values-cs/strings.xml1
-rw-r--r--core/res/res/values-da/strings.xml5
-rw-r--r--core/res/res/values-de/strings.xml3
-rw-r--r--core/res/res/values-el/strings.xml3
-rw-r--r--core/res/res/values-en-rAU/strings.xml9
-rw-r--r--core/res/res/values-en-rCA/strings.xml9
-rw-r--r--core/res/res/values-en-rGB/strings.xml9
-rw-r--r--core/res/res/values-en-rIN/strings.xml9
-rw-r--r--core/res/res/values-en-rXC/strings.xml1
-rw-r--r--core/res/res/values-es-rUS/strings.xml5
-rw-r--r--core/res/res/values-es/strings.xml1
-rw-r--r--core/res/res/values-et/strings.xml1
-rw-r--r--core/res/res/values-eu/strings.xml21
-rw-r--r--core/res/res/values-fa/strings.xml3
-rw-r--r--core/res/res/values-fi/strings.xml3
-rw-r--r--core/res/res/values-fr-rCA/strings.xml1
-rw-r--r--core/res/res/values-fr/strings.xml1
-rw-r--r--core/res/res/values-gl/strings.xml7
-rw-r--r--core/res/res/values-gu/strings.xml1
-rw-r--r--core/res/res/values-hi/strings.xml1
-rw-r--r--core/res/res/values-hr/strings.xml5
-rw-r--r--core/res/res/values-hu/strings.xml3
-rw-r--r--core/res/res/values-hy/strings.xml1
-rw-r--r--core/res/res/values-in/strings.xml5
-rw-r--r--core/res/res/values-is/strings.xml5
-rw-r--r--core/res/res/values-it/strings.xml5
-rw-r--r--core/res/res/values-iw/strings.xml1
-rw-r--r--core/res/res/values-ja/strings.xml3
-rw-r--r--core/res/res/values-ka/strings.xml1
-rw-r--r--core/res/res/values-kk/strings.xml1
-rw-r--r--core/res/res/values-km/strings.xml1
-rw-r--r--core/res/res/values-kn/strings.xml5
-rw-r--r--core/res/res/values-ko/strings.xml1
-rw-r--r--core/res/res/values-ky/strings.xml19
-rw-r--r--core/res/res/values-lo/strings.xml3
-rw-r--r--core/res/res/values-lt/strings.xml1
-rw-r--r--core/res/res/values-lv/strings.xml1
-rw-r--r--core/res/res/values-mk/strings.xml9
-rw-r--r--core/res/res/values-ml/strings.xml59
-rw-r--r--core/res/res/values-mn/strings.xml73
-rw-r--r--core/res/res/values-mr/strings.xml1
-rw-r--r--core/res/res/values-ms/strings.xml1
-rw-r--r--core/res/res/values-my/strings.xml1
-rw-r--r--core/res/res/values-nb/strings.xml1
-rw-r--r--core/res/res/values-ne/strings.xml9
-rw-r--r--core/res/res/values-nl/strings.xml3
-rw-r--r--core/res/res/values-or/strings.xml63
-rw-r--r--core/res/res/values-pa/strings.xml1
-rw-r--r--core/res/res/values-pl/strings.xml3
-rw-r--r--core/res/res/values-pt-rBR/strings.xml3
-rw-r--r--core/res/res/values-pt-rPT/strings.xml9
-rw-r--r--core/res/res/values-pt/strings.xml3
-rw-r--r--core/res/res/values-ro/strings.xml3
-rw-r--r--core/res/res/values-ru/strings.xml3
-rw-r--r--core/res/res/values-si/strings.xml1
-rw-r--r--core/res/res/values-sk/strings.xml11
-rw-r--r--core/res/res/values-sl/strings.xml3
-rw-r--r--core/res/res/values-sq/strings.xml1
-rw-r--r--core/res/res/values-sr/strings.xml1
-rw-r--r--core/res/res/values-sv/strings.xml5
-rw-r--r--core/res/res/values-sw/strings.xml3
-rw-r--r--core/res/res/values-ta/strings.xml1
-rw-r--r--core/res/res/values-te/strings.xml5
-rw-r--r--core/res/res/values-th/strings.xml5
-rw-r--r--core/res/res/values-tl/strings.xml1
-rw-r--r--core/res/res/values-tr/strings.xml3
-rw-r--r--core/res/res/values-uk/strings.xml9
-rw-r--r--core/res/res/values-ur/strings.xml3
-rw-r--r--core/res/res/values-uz/strings.xml5
-rw-r--r--core/res/res/values-vi/strings.xml1
-rw-r--r--core/res/res/values-zh-rCN/strings.xml5
-rw-r--r--core/res/res/values-zh-rHK/strings.xml5
-rw-r--r--core/res/res/values-zh-rTW/strings.xml5
-rw-r--r--core/res/res/values-zu/strings.xml1
-rw-r--r--core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v1.apk (renamed from core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch.apk)bin16854 -> 16854 bytes
-rw-r--r--core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v2.apkbin0 -> 16854 bytes
-rw-r--r--core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v3.apkbin0 -> 16854 bytes
-rw-r--r--core/tests/coretests/assets/SourceStampVerifierTest/stamp-certificate-mismatch.apkbin16854 -> 12758 bytes
-rw-r--r--core/tests/coretests/assets/SourceStampVerifierTest/stamp-malformed-signature.apkbin16854 -> 12758 bytes
-rw-r--r--core/tests/coretests/assets/SourceStampVerifierTest/stamp-without-block.apkbin12758 -> 12758 bytes
-rw-r--r--core/tests/coretests/assets/SourceStampVerifierTest/valid-stamp.apkbin16854 -> 16854 bytes
-rw-r--r--core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java117
-rw-r--r--data/etc/car/Android.bp7
-rw-r--r--data/etc/car/com.android.car.companiondevicesupport.xml24
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--keystore/java/android/security/KeyStore.java70
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java14
-rw-r--r--media/java/android/media/MediaRouter2.java2
-rw-r--r--media/java/android/media/MediaRouter2Manager.java2
-rw-r--r--media/java/android/media/tv/tuner/filter/MediaEvent.java19
-rw-r--r--media/jni/android_media_tv_Tuner.cpp13
-rw-r--r--media/jni/android_media_tv_Tuner.h2
-rw-r--r--mime/java-res/android.mime.types1
-rw-r--r--packages/CarSystemUI/res/xml/overlayable.xml23
-rw-r--r--packages/PrintSpooler/res/values-ca/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml2
-rw-r--r--packages/Shell/AndroidManifest.xml2
-rw-r--r--packages/SoundPicker/AndroidManifest.xml1
-rw-r--r--packages/SoundPicker/res/values/strings.xml3
-rw-r--r--packages/SystemUI/res-product/values-mn/strings.xml2
-rw-r--r--packages/SystemUI/res/drawable/bubble_stack_user_education_bg_rtl.xml22
-rw-r--r--packages/SystemUI/res/layout/bubble_stack_user_education.xml4
-rw-r--r--packages/SystemUI/res/layout/bubbles_manage_button_education.xml10
-rw-r--r--packages/SystemUI/res/layout/global_actions_power_dialog.xml24
-rw-r--r--packages/SystemUI/res/layout/global_actions_power_item.xml45
-rw-r--r--packages/SystemUI/res/layout/home_handle.xml1
-rw-r--r--packages/SystemUI/res/values-af/strings.xml9
-rw-r--r--packages/SystemUI/res/values-am/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml5
-rw-r--r--packages/SystemUI/res/values-as/strings.xml5
-rw-r--r--packages/SystemUI/res/values-az/strings.xml9
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml11
-rw-r--r--packages/SystemUI/res/values-be/strings.xml9
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml11
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml9
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml17
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml9
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml7
-rw-r--r--packages/SystemUI/res/values-da/strings.xml15
-rw-r--r--packages/SystemUI/res/values-de/strings.xml6
-rw-r--r--packages/SystemUI/res/values-el/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml3
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml13
-rw-r--r--packages/SystemUI/res/values-es/strings.xml15
-rw-r--r--packages/SystemUI/res/values-et/strings.xml5
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml11
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml5
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml13
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml9
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml11
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml5
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml5
-rw-r--r--packages/SystemUI/res/values-in/strings.xml5
-rw-r--r--packages/SystemUI/res/values-is/strings.xml7
-rw-r--r--packages/SystemUI/res/values-it/strings.xml11
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml11
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml5
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml15
-rw-r--r--packages/SystemUI/res/values-km/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml11
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml19
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml5
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml5
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml7
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml12
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml9
-rw-r--r--packages/SystemUI/res/values-my/strings.xml5
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml16
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml5
-rw-r--r--packages/SystemUI/res/values-or/strings.xml12
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml15
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml27
-rw-r--r--packages/SystemUI/res/values-si/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml21
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml11
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml3
-rw-r--r--packages/SystemUI/res/values-te/strings.xml3
-rw-r--r--packages/SystemUI/res/values-th/strings.xml3
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml9
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml15
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml9
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml21
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml5
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml5
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/res/values/ids.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml67
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java15
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt133
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt184
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java236
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java136
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleManageEducationView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java131
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java120
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPowerDialog.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt120
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java132
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java233
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java)61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java78
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt (renamed from packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/FloatProperties.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/Events.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java129
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt256
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt212
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java45
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt126
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java)123
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java161
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java5
-rw-r--r--packages/Tethering/OWNERS2
-rw-r--r--packages/Tethering/jarjar-rules.txt18
-rw-r--r--packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java2
-rw-r--r--packages/Tethering/src/android/net/ip/IpServer.java9
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java171
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/Tethering.java40
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java14
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java5
-rw-r--r--packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java47
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java395
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java8
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java6
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java9
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java43
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java6
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java65
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java15
-rw-r--r--services/backup/java/com/android/server/backup/restore/FullRestoreEngineThread.java4
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java3
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java45
-rw-r--r--services/core/java/android/os/UserManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java42
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java36
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java29
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java10
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java35
-rw-r--r--services/core/java/com/android/server/gpu/GpuService.java77
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java104
-rw-r--r--services/core/java/com/android/server/media/BluetoothRouteProvider.java18
-rw-r--r--services/core/java/com/android/server/media/MediaButtonReceiverHolder.java3
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java12
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java3
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java19
-rw-r--r--services/core/java/com/android/server/notification/NotificationHistoryDatabase.java43
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java2
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java75
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java30
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java4
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java27
-rw-r--r--services/core/java/com/android/server/power/batterysaver/BatterySaverController.java3
-rw-r--r--services/core/java/com/android/server/storage/AppFuseBridge.java12
-rw-r--r--services/core/java/com/android/server/storage/StorageSessionController.java5
-rw-r--r--services/core/java/com/android/server/storage/StorageUserConnection.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java9
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/BLASTSyncEngine.java33
-rw-r--r--services/core/java/com/android/server/wm/DisplayArea.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java6
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java2
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java37
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java5
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java4
-rw-r--r--services/core/java/com/android/server/wm/SurfaceAnimationRunner.java3
-rw-r--r--services/core/java/com/android/server/wm/Task.java22
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java18
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java18
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java46
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java38
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java53
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java33
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java20
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java81
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java2
-rw-r--r--services/core/jni/Android.bp2
-rw-r--r--services/core/jni/com_android_server_gpu_GpuService.cpp66
-rw-r--r--services/core/jni/com_android_server_storage_AppFuseBridge.cpp18
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java2
-rw-r--r--services/java/com/android/server/SystemConfigService.java16
-rw-r--r--services/net/java/android/net/ip/IpClientCallbacks.java13
-rw-r--r--services/tests/PackageManagerServiceTests/host/Android.bp8
-rw-r--r--services/tests/PackageManagerServiceTests/host/resources/PackageManagerDummyAppVersion3Invalid.apkbin0 -> 2457 bytes
-rw-r--r--services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt10
-rw-r--r--services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt83
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/Android.bp5
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml9
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml9
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml9
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml28
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java17
-rw-r--r--services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apkbin2075621 -> 2075621 bytes
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java2
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/slice/SliceClientPermissionsTest.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java47
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java37
-rw-r--r--telephony/common/com/android/internal/telephony/CarrierAppUtils.java158
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java9
-rw-r--r--tests/net/common/java/android/net/DhcpInfoTest.java3
-rw-r--r--tests/net/java/android/net/DnsPacketTest.java159
-rw-r--r--tests/net/java/android/net/NetworkUtilsTest.java60
-rw-r--r--wifi/jarjar-rules.txt3
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java30
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java3
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java7
509 files changed, 7852 insertions, 4027 deletions
diff --git a/Android.bp b/Android.bp
index 7c2d6eb9301e..ec7740437c2d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -701,7 +701,6 @@ filegroup {
"core/java/com/android/internal/util/TrafficStatsConstants.java",
"core/java/com/android/internal/util/WakeupMessage.java",
"core/java/com/android/internal/util/TokenBucket.java",
- "core/java/android/net/shared/*.java",
],
}
@@ -709,7 +708,6 @@ filegroup {
name: "framework-services-net-module-wifi-shared-srcs",
srcs: [
"core/java/android/net/DhcpResults.java",
- "core/java/android/net/shared/InetAddressUtils.java",
"core/java/android/net/util/IpUtils.java",
"core/java/android/util/LocalLog.java",
],
@@ -726,7 +724,6 @@ filegroup {
"core/java/com/android/internal/util/State.java",
"core/java/com/android/internal/util/StateMachine.java",
"core/java/com/android/internal/util/TrafficStatsConstants.java",
- "core/java/android/net/shared/Inet4AddressUtils.java",
],
}
@@ -1163,7 +1160,6 @@ java_library {
srcs: [
"core/java/android/content/pm/BaseParceledListSlice.java",
"core/java/android/content/pm/ParceledListSlice.java",
- "core/java/android/net/shared/Inet4AddressUtils.java",
"core/java/android/os/HandlerExecutor.java",
"core/java/com/android/internal/util/AsyncChannel.java",
"core/java/com/android/internal/util/AsyncService.java",
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index 7e8c90632fd9..4d29045fa631 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -29,6 +29,8 @@ import static android.app.blob.XmlTags.TAG_COMMITTER;
import static android.app.blob.XmlTags.TAG_LEASEE;
import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.O_RDONLY;
+import static android.text.format.Formatter.FLAG_IEC_UNITS;
+import static android.text.format.Formatter.formatFileSize;
import static com.android.server.blob.BlobStoreConfig.TAG;
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_COMMIT_TIME;
@@ -335,7 +337,9 @@ class BlobMetadata {
}
void forEachLeasee(Consumer<Leasee> consumer) {
- mLeasees.forEach(consumer);
+ synchronized (mMetadataLock) {
+ mLeasees.forEach(consumer);
+ }
}
File getBlobFile() {
@@ -354,7 +358,11 @@ class BlobMetadata {
throw e.rethrowAsIOException();
}
try {
- return createRevocableFd(fd, callingPackage);
+ if (BlobStoreConfig.shouldUseRevocableFdForReads()) {
+ return createRevocableFd(fd, callingPackage);
+ } else {
+ return new ParcelFileDescriptor(fd);
+ }
} catch (IOException e) {
IoUtils.closeQuietly(fd);
throw e;
@@ -460,54 +468,57 @@ class BlobMetadata {
}
void dump(IndentingPrintWriter fout, DumpArgs dumpArgs) {
- fout.println("blobHandle:");
- fout.increaseIndent();
- mBlobHandle.dump(fout, dumpArgs.shouldDumpFull());
- fout.decreaseIndent();
-
- fout.println("Committers:");
- fout.increaseIndent();
- if (mCommitters.isEmpty()) {
- fout.println("<empty>");
- } else {
- for (int i = 0, count = mCommitters.size(); i < count; ++i) {
- final Committer committer = mCommitters.valueAt(i);
- fout.println("committer " + committer.toString());
- fout.increaseIndent();
- committer.dump(fout);
- fout.decreaseIndent();
+ synchronized (mMetadataLock) {
+ fout.println("blobHandle:");
+ fout.increaseIndent();
+ mBlobHandle.dump(fout, dumpArgs.shouldDumpFull());
+ fout.decreaseIndent();
+ fout.println("size: " + formatFileSize(mContext, getSize(), FLAG_IEC_UNITS));
+
+ fout.println("Committers:");
+ fout.increaseIndent();
+ if (mCommitters.isEmpty()) {
+ fout.println("<empty>");
+ } else {
+ for (int i = 0, count = mCommitters.size(); i < count; ++i) {
+ final Committer committer = mCommitters.valueAt(i);
+ fout.println("committer " + committer.toString());
+ fout.increaseIndent();
+ committer.dump(fout);
+ fout.decreaseIndent();
+ }
}
- }
- fout.decreaseIndent();
+ fout.decreaseIndent();
- fout.println("Leasees:");
- fout.increaseIndent();
- if (mLeasees.isEmpty()) {
- fout.println("<empty>");
- } else {
- for (int i = 0, count = mLeasees.size(); i < count; ++i) {
- final Leasee leasee = mLeasees.valueAt(i);
- fout.println("leasee " + leasee.toString());
- fout.increaseIndent();
- leasee.dump(mContext, fout);
- fout.decreaseIndent();
+ fout.println("Leasees:");
+ fout.increaseIndent();
+ if (mLeasees.isEmpty()) {
+ fout.println("<empty>");
+ } else {
+ for (int i = 0, count = mLeasees.size(); i < count; ++i) {
+ final Leasee leasee = mLeasees.valueAt(i);
+ fout.println("leasee " + leasee.toString());
+ fout.increaseIndent();
+ leasee.dump(mContext, fout);
+ fout.decreaseIndent();
+ }
}
- }
- fout.decreaseIndent();
-
- fout.println("Open fds:");
- fout.increaseIndent();
- if (mRevocableFds.isEmpty()) {
- fout.println("<empty>");
- } else {
- for (int i = 0, count = mRevocableFds.size(); i < count; ++i) {
- final String packageName = mRevocableFds.keyAt(i);
- final ArraySet<RevocableFileDescriptor> packageFds =
- mRevocableFds.valueAt(i);
- fout.println(packageName + "#" + packageFds.size());
+ fout.decreaseIndent();
+
+ fout.println("Open fds:");
+ fout.increaseIndent();
+ if (mRevocableFds.isEmpty()) {
+ fout.println("<empty>");
+ } else {
+ for (int i = 0, count = mRevocableFds.size(); i < count; ++i) {
+ final String packageName = mRevocableFds.keyAt(i);
+ final ArraySet<RevocableFileDescriptor> packageFds =
+ mRevocableFds.valueAt(i);
+ fout.println(packageName + "#" + packageFds.size());
+ }
}
+ fout.decreaseIndent();
}
- fout.decreaseIndent();
}
void writeToXml(XmlSerializer out) throws IOException {
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
index 08ee24460722..d780d5dab14d 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
@@ -122,6 +122,15 @@ class BlobStoreConfig {
public static long COMMIT_COOL_OFF_DURATION_MS =
DEFAULT_COMMIT_COOL_OFF_DURATION_MS;
+ /**
+ * Denotes whether to use RevocableFileDescriptor when apps try to read session/blob data.
+ */
+ public static final String KEY_USE_REVOCABLE_FD_FOR_READS =
+ "use_revocable_fd_for_reads";
+ public static final boolean DEFAULT_USE_REVOCABLE_FD_FOR_READS = true;
+ public static boolean USE_REVOCABLE_FD_FOR_READS =
+ DEFAULT_USE_REVOCABLE_FD_FOR_READS;
+
static void refresh(Properties properties) {
if (!NAMESPACE_BLOBSTORE.equals(properties.getNamespace())) {
return;
@@ -151,6 +160,10 @@ class BlobStoreConfig {
COMMIT_COOL_OFF_DURATION_MS = properties.getLong(key,
DEFAULT_COMMIT_COOL_OFF_DURATION_MS);
break;
+ case KEY_USE_REVOCABLE_FD_FOR_READS:
+ USE_REVOCABLE_FD_FOR_READS = properties.getBoolean(key,
+ DEFAULT_USE_REVOCABLE_FD_FOR_READS);
+ break;
default:
Slog.wtf(TAG, "Unknown key in device config properties: " + key);
}
@@ -178,6 +191,8 @@ class BlobStoreConfig {
fout.println(String.format(dumpFormat, KEY_COMMIT_COOL_OFF_DURATION_MS,
TimeUtils.formatDuration(COMMIT_COOL_OFF_DURATION_MS),
TimeUtils.formatDuration(DEFAULT_COMMIT_COOL_OFF_DURATION_MS)));
+ fout.println(String.format(dumpFormat, KEY_USE_REVOCABLE_FD_FOR_READS,
+ USE_REVOCABLE_FD_FOR_READS, DEFAULT_USE_REVOCABLE_FD_FOR_READS));
}
}
@@ -242,6 +257,13 @@ class BlobStoreConfig {
< System.currentTimeMillis();
}
+ /**
+ * Return whether to use RevocableFileDescriptor when apps try to read session/blob data.
+ */
+ public static boolean shouldUseRevocableFdForReads() {
+ return DeviceConfigProperties.USE_REVOCABLE_FD_FOR_READS;
+ }
+
@Nullable
public static File prepareBlobFile(long sessionId) {
final File blobsDir = prepareBlobsDir();
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 381efc10b416..78eab0b0a21e 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -1070,10 +1070,8 @@ public class BlobStoreManagerService extends SystemService {
return shouldRemove;
});
}
- if (LOGV) {
- Slog.v(TAG, "Completed idle maintenance; deleted "
- + Arrays.toString(deletedBlobIds.toArray()));
- }
+ Slog.d(TAG, "Completed idle maintenance; deleted "
+ + Arrays.toString(deletedBlobIds.toArray()));
writeBlobSessionsAsync();
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index 77ca4aa7a9e6..baafff53d072 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -27,6 +27,8 @@ import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_RDWR;
import static android.system.OsConstants.SEEK_SET;
+import static android.text.format.Formatter.FLAG_IEC_UNITS;
+import static android.text.format.Formatter.formatFileSize;
import static com.android.server.blob.BlobStoreConfig.TAG;
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_SESSION_CREATION_TIME;
@@ -266,6 +268,13 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
throw new IllegalStateException("Not allowed to read in state: "
+ stateToString(mState));
}
+ if (!BlobStoreConfig.shouldUseRevocableFdForReads()) {
+ try {
+ return new ParcelFileDescriptor(openReadInternal());
+ } catch (IOException e) {
+ throw ExceptionUtils.wrap(e);
+ }
+ }
}
FileDescriptor fd = null;
@@ -281,7 +290,6 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
trackRevocableFdLocked(revocableFd);
return revocableFd.getRevocableFileDescriptor();
}
-
} catch (IOException e) {
IoUtils.closeQuietly(fd);
throw ExceptionUtils.wrap(e);
@@ -533,6 +541,7 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
fout.println("ownerUid: " + mOwnerUid);
fout.println("ownerPkg: " + mOwnerPackageName);
fout.println("creation time: " + BlobStoreUtils.formatTime(mCreationTimeMs));
+ fout.println("size: " + formatFileSize(mContext, getSize(), FLAG_IEC_UNITS));
fout.println("blobHandle:");
fout.increaseIndent();
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 062108757349..5ceea2aedb85 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -82,10 +82,10 @@ import android.os.BatteryStats;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
+import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
-import android.os.PowerWhitelistManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -93,7 +93,6 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings.Global;
import android.telephony.TelephonyManager;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.KeyValueListParser;
import android.util.Slog;
@@ -205,6 +204,10 @@ public class AppStandbyController implements AppStandbyInternal {
*/
private static final long WAIT_FOR_ADMIN_DATA_TIMEOUT_MS = 10_000;
+ private static final int HEADLESS_APP_CHECK_FLAGS =
+ PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS;
+
// To name the lock for stack traces
static class Lock {}
@@ -234,7 +237,7 @@ public class AppStandbyController implements AppStandbyInternal {
* disabled). Presence in this map indicates that the app is a headless system app.
*/
@GuardedBy("mHeadlessSystemApps")
- private final ArrayMap<String, Boolean> mHeadlessSystemApps = new ArrayMap<>();
+ private final ArraySet<String> mHeadlessSystemApps = new ArraySet<>();
private final CountDownLatch mAdminDataAvailableLatch = new CountDownLatch(1);
@@ -387,6 +390,7 @@ public class AppStandbyController implements AppStandbyInternal {
DeviceStateReceiver deviceStateReceiver = new DeviceStateReceiver();
IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING);
deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
+ deviceStates.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
mContext.registerReceiver(deviceStateReceiver, deviceStates);
synchronized (mAppIdleLock) {
@@ -442,6 +446,9 @@ public class AppStandbyController implements AppStandbyInternal {
mSystemServicesReady = true;
+ // Offload to handler thread to avoid boot time impact.
+ mHandler.post(mInjector::updatePowerWhitelistCache);
+
boolean userFileExists;
synchronized (mAppIdleLock) {
userFileExists = mAppIdleHistory.userFileExists(UserHandle.USER_SYSTEM);
@@ -1080,15 +1087,11 @@ public class AppStandbyController implements AppStandbyInternal {
return STANDBY_BUCKET_EXEMPTED;
}
if (mSystemServicesReady) {
- try {
- // We allow all whitelisted apps, including those that don't want to be whitelisted
- // for idle mode, because app idle (aka app standby) is really not as big an issue
- // for controlling who participates vs. doze mode.
- if (mInjector.isNonIdleWhitelisted(packageName)) {
- return STANDBY_BUCKET_EXEMPTED;
- }
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
+ // We allow all whitelisted apps, including those that don't want to be whitelisted
+ // for idle mode, because app idle (aka app standby) is really not as big an issue
+ // for controlling who participates vs. doze mode.
+ if (mInjector.isNonIdleWhitelisted(packageName)) {
+ return STANDBY_BUCKET_EXEMPTED;
}
if (isActiveDeviceAdmin(packageName, userId)) {
@@ -1123,7 +1126,7 @@ public class AppStandbyController implements AppStandbyInternal {
private boolean isHeadlessSystemApp(String packageName) {
synchronized (mHeadlessSystemApps) {
- return mHeadlessSystemApps.containsKey(packageName);
+ return mHeadlessSystemApps.contains(packageName);
}
}
@@ -1695,9 +1698,8 @@ public class AppStandbyController implements AppStandbyInternal {
return;
}
try {
- PackageInfo pi = mPackageManager.getPackageInfoAsUser(packageName,
- PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS,
- userId);
+ PackageInfo pi = mPackageManager.getPackageInfoAsUser(
+ packageName, HEADLESS_APP_CHECK_FLAGS, userId);
evaluateSystemAppException(pi);
} catch (PackageManager.NameNotFoundException e) {
synchronized (mHeadlessSystemApps) {
@@ -1709,15 +1711,16 @@ public class AppStandbyController implements AppStandbyInternal {
/** Returns true if the exception status changed. */
private boolean evaluateSystemAppException(@Nullable PackageInfo pkgInfo) {
if (pkgInfo == null || pkgInfo.applicationInfo == null
- || !pkgInfo.applicationInfo.isSystemApp()) {
+ || (!pkgInfo.applicationInfo.isSystemApp()
+ && !pkgInfo.applicationInfo.isUpdatedSystemApp())) {
return false;
}
synchronized (mHeadlessSystemApps) {
if (pkgInfo.activities == null || pkgInfo.activities.length == 0) {
// Headless system app.
- return mHeadlessSystemApps.put(pkgInfo.packageName, true) == null;
+ return mHeadlessSystemApps.add(pkgInfo.packageName);
} else {
- return mHeadlessSystemApps.remove(pkgInfo.packageName) != null;
+ return mHeadlessSystemApps.remove(pkgInfo.packageName);
}
}
}
@@ -1754,12 +1757,11 @@ public class AppStandbyController implements AppStandbyInternal {
}
}
- /** Call on a system update to temporarily reset system app buckets. */
+ /** Call on system boot to get the initial set of headless system apps. */
private void loadHeadlessSystemAppCache() {
Slog.d(TAG, "Loading headless system app cache. appIdleEnabled=" + mAppIdleEnabled);
final List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(
- PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS,
- UserHandle.USER_SYSTEM);
+ HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM);
final int packageCount = packages.size();
for (int i = 0; i < packageCount; i++) {
PackageInfo pkgInfo = packages.get(i);
@@ -1807,8 +1809,6 @@ public class AppStandbyController implements AppStandbyInternal {
+ "): " + mCarrierPrivilegedApps);
}
- final long now = System.currentTimeMillis();
-
pw.println();
pw.println("Settings:");
@@ -1868,12 +1868,14 @@ public class AppStandbyController implements AppStandbyInternal {
synchronized (mHeadlessSystemApps) {
for (int i = mHeadlessSystemApps.size() - 1; i >= 0; --i) {
pw.print(" ");
- pw.print(mHeadlessSystemApps.keyAt(i));
+ pw.print(mHeadlessSystemApps.valueAt(i));
pw.println(",");
}
}
pw.println("]");
pw.println();
+
+ mInjector.dump(pw);
}
/**
@@ -1890,7 +1892,7 @@ public class AppStandbyController implements AppStandbyInternal {
private PackageManagerInternal mPackageManagerInternal;
private DisplayManager mDisplayManager;
private PowerManager mPowerManager;
- private PowerWhitelistManager mPowerWhitelistManager;
+ private IDeviceIdleController mDeviceIdleController;
private CrossProfileAppsInternal mCrossProfileAppsInternal;
int mBootPhase;
/**
@@ -1898,6 +1900,11 @@ public class AppStandbyController implements AppStandbyInternal {
* automatically placed in the RESTRICTED bucket.
*/
long mAutoRestrictedBucketDelayMs = ONE_DAY;
+ /**
+ * Cached set of apps that are power whitelisted, including those not whitelisted from idle.
+ */
+ @GuardedBy("mPowerWhitelistedApps")
+ private final ArraySet<String> mPowerWhitelistedApps = new ArraySet<>();
Injector(Context context, Looper looper) {
mContext = context;
@@ -1914,7 +1921,8 @@ public class AppStandbyController implements AppStandbyInternal {
void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
- mPowerWhitelistManager = mContext.getSystemService(PowerWhitelistManager.class);
+ mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
mBatteryStats = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
@@ -1965,8 +1973,34 @@ public class AppStandbyController implements AppStandbyInternal {
return mBatteryManager.isCharging();
}
- boolean isNonIdleWhitelisted(String packageName) throws RemoteException {
- return mPowerWhitelistManager.isWhitelisted(packageName, false);
+ boolean isNonIdleWhitelisted(String packageName) {
+ if (mBootPhase < PHASE_SYSTEM_SERVICES_READY) {
+ return false;
+ }
+ synchronized (mPowerWhitelistedApps) {
+ return mPowerWhitelistedApps.contains(packageName);
+ }
+ }
+
+ private void updatePowerWhitelistCache() {
+ if (mBootPhase < PHASE_SYSTEM_SERVICES_READY) {
+ return;
+ }
+ try {
+ // Don't call out to DeviceIdleController with the lock held.
+ final String[] whitelistedPkgs =
+ mDeviceIdleController.getFullPowerWhitelistExceptIdle();
+ synchronized (mPowerWhitelistedApps) {
+ mPowerWhitelistedApps.clear();
+ final int len = whitelistedPkgs.length;
+ for (int i = 0; i < len; ++i) {
+ mPowerWhitelistedApps.add(whitelistedPkgs[i]);
+ }
+ }
+ } catch (RemoteException e) {
+ // Should not happen.
+ Slog.wtf(TAG, "Failed to get power whitelist", e);
+ }
}
boolean isRestrictedBucketEnabled() {
@@ -2053,6 +2087,19 @@ public class AppStandbyController implements AppStandbyInternal {
}
return mCrossProfileAppsInternal.getTargetUserProfiles(pkg, userId);
}
+
+ void dump(PrintWriter pw) {
+ pw.println("mPowerWhitelistedApps=[");
+ synchronized (mPowerWhitelistedApps) {
+ for (int i = mPowerWhitelistedApps.size() - 1; i >= 0; --i) {
+ pw.print(" ");
+ pw.print(mPowerWhitelistedApps.valueAt(i));
+ pw.println(",");
+ }
+ }
+ pw.println("]");
+ pw.println();
+ }
}
class AppStandbyHandler extends Handler {
@@ -2138,6 +2185,11 @@ public class AppStandbyController implements AppStandbyInternal {
case BatteryManager.ACTION_DISCHARGING:
setChargingState(false);
break;
+ case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED:
+ if (mSystemServicesReady) {
+ mHandler.post(mInjector::updatePowerWhitelistCache);
+ }
+ break;
}
}
}
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 19f578ecfc66..8a3fbde5609b 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
+import com.google.android.exoplayer2.extractor.ChunkIndex;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
@@ -817,6 +818,30 @@ public final class MediaParser {
public static final String PARAMETER_EXPOSE_DUMMY_SEEKMAP =
"android.media.mediaparser.exposeDummySeekMap";
+ /**
+ * Sets whether chunk indices available in the extracted media should be exposed as {@link
+ * MediaFormat MediaFormats}. {@code boolean} expected. Default value is {@link false}.
+ *
+ * <p>When set to true, any information about media segmentation will be exposed as a {@link
+ * MediaFormat} (with track index 0) containing four {@link ByteBuffer} elements under the
+ * following keys:
+ *
+ * <ul>
+ * <li>"chunk-index-int-sizes": Contains {@code ints} representing the sizes in bytes of each
+ * of the media segments.
+ * <li>"chunk-index-long-offsets": Contains {@code longs} representing the byte offsets of
+ * each segment in the stream.
+ * <li>"chunk-index-long-us-durations": Contains {@code longs} representing the media duration
+ * of each segment, in microseconds.
+ * <li>"chunk-index-long-us-times": Contains {@code longs} representing the start time of each
+ * segment, in microseconds.
+ * </ul>
+ *
+ * @hide
+ */
+ public static final String PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT =
+ "android.media.mediaParser.exposeChunkIndexAsMediaFormat";
+
// Private constants.
private static final String TAG = "MediaParser";
@@ -980,6 +1005,7 @@ public final class MediaParser {
private boolean mIgnoreTimestampOffset;
private boolean mEagerlyExposeTrackType;
private boolean mExposeDummySeekMap;
+ private boolean mExposeChunkIndexAsMediaFormat;
private String mParserName;
private Extractor mExtractor;
private ExtractorInput mExtractorInput;
@@ -1042,6 +1068,9 @@ public final class MediaParser {
if (PARAMETER_EXPOSE_DUMMY_SEEKMAP.equals(parameterName)) {
mExposeDummySeekMap = (boolean) value;
}
+ if (PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT.equals(parameterName)) {
+ mExposeChunkIndexAsMediaFormat = (boolean) value;
+ }
mParserParameters.put(parameterName, value);
return this;
}
@@ -1436,6 +1465,19 @@ public final class MediaParser {
@Override
public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
+ if (mExposeChunkIndexAsMediaFormat && exoplayerSeekMap instanceof ChunkIndex) {
+ ChunkIndex chunkIndex = (ChunkIndex) exoplayerSeekMap;
+ MediaFormat mediaFormat = new MediaFormat();
+ mediaFormat.setByteBuffer("chunk-index-int-sizes", toByteBuffer(chunkIndex.sizes));
+ mediaFormat.setByteBuffer(
+ "chunk-index-long-offsets", toByteBuffer(chunkIndex.offsets));
+ mediaFormat.setByteBuffer(
+ "chunk-index-long-us-durations", toByteBuffer(chunkIndex.durationsUs));
+ mediaFormat.setByteBuffer(
+ "chunk-index-long-us-times", toByteBuffer(chunkIndex.timesUs));
+ mOutputConsumer.onTrackDataFound(
+ /* trackIndex= */ 0, new TrackData(mediaFormat, /* drmInitData= */ null));
+ }
mOutputConsumer.onSeekMapFound(new SeekMap(exoplayerSeekMap));
}
}
@@ -1823,6 +1865,24 @@ public final class MediaParser {
return result;
}
+ private static ByteBuffer toByteBuffer(long[] longArray) {
+ ByteBuffer byteBuffer = ByteBuffer.allocateDirect(longArray.length * Long.BYTES);
+ for (long element : longArray) {
+ byteBuffer.putLong(element);
+ }
+ byteBuffer.flip();
+ return byteBuffer;
+ }
+
+ private static ByteBuffer toByteBuffer(int[] intArray) {
+ ByteBuffer byteBuffer = ByteBuffer.allocateDirect(intArray.length * Integer.BYTES);
+ for (int element : intArray) {
+ byteBuffer.putInt(element);
+ }
+ byteBuffer.flip();
+ return byteBuffer;
+ }
+
private static String toTypeString(int type) {
switch (type) {
case C.TRACK_TYPE_VIDEO:
@@ -1979,6 +2039,8 @@ public final class MediaParser {
expectedTypeByParameterName.put(PARAMETER_IGNORE_TIMESTAMP_OFFSET, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_EAGERLY_EXPOSE_TRACKTYPE, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_EXPOSE_DUMMY_SEEKMAP, Boolean.class);
+ expectedTypeByParameterName.put(
+ PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT, Boolean.class);
EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
}
}
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 15a2f22e0fea..8a0f66040711 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -88,27 +88,4 @@ java_sdk_library {
"com.android.os.statsd",
"test_com.android.os.statsd",
],
-}
-
-android_test {
- name: "FrameworkStatsdTest",
- platform_apis: true,
- srcs: [
- // TODO(b/147705194): Use framework-statsd as a lib dependency instead.
- ":framework-statsd-sources",
- "test/**/*.java",
- ],
- manifest: "test/AndroidManifest.xml",
- static_libs: [
- "androidx.test.rules",
- "truth-prebuilt",
- ],
- libs: [
- "android.test.runner.stubs",
- "android.test.base.stubs",
- ],
- test_suites: [
- "device-tests",
- ],
-}
-
+} \ No newline at end of file
diff --git a/apex/statsd/framework/test/Android.bp b/apex/statsd/framework/test/Android.bp
new file mode 100644
index 000000000000..b113d595b57c
--- /dev/null
+++ b/apex/statsd/framework/test/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "FrameworkStatsdTest",
+ platform_apis: true,
+ srcs: [
+ // TODO(b/147705194): Use framework-statsd as a lib dependency instead.
+ ":framework-statsd-sources",
+ "**/*.java",
+ ],
+ manifest: "AndroidManifest.xml",
+ static_libs: [
+ "androidx.test.rules",
+ "truth-prebuilt",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ test_suites: [
+ "device-tests",
+ "mts",
+ ],
+} \ No newline at end of file
diff --git a/apex/statsd/framework/test/AndroidTest.xml b/apex/statsd/framework/test/AndroidTest.xml
new file mode 100644
index 000000000000..fb519150ecd5
--- /dev/null
+++ b/apex/statsd/framework/test/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Tests for Statsd.">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="FrameworkStatsdTest.apk" />
+ <option name="install-arg" value="-g" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="mts" />
+ <option name="test-tag" value="FrameworkStatsdTest" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.os.statsd.framework.test" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
+ </object>
+</configuration> \ No newline at end of file
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 7a445a4cf8a8..dc20a02156cb 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -43,6 +43,7 @@ import "frameworks/base/core/proto/android/server/location/enums.proto";
import "frameworks/base/core/proto/android/service/procstats_enum.proto";
import "frameworks/base/core/proto/android/service/usb.proto";
import "frameworks/base/core/proto/android/stats/connectivity/network_stack.proto";
+import "frameworks/base/core/proto/android/stats/connectivity/tethering.proto";
import "frameworks/base/core/proto/android/stats/dnsresolver/dns_resolver.proto";
import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
@@ -482,6 +483,9 @@ message Atom {
BlobLeased blob_leased = 299 [(module) = "framework"];
BlobOpened blob_opened = 300 [(module) = "framework"];
ContactsProviderStatusReported contacts_provider_status_reported = 301;
+ KeystoreKeyEventReported keystore_key_event_reported = 302;
+ NetworkTetheringReported network_tethering_reported =
+ 303 [(module) = "network_tethering"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
@@ -6890,6 +6894,24 @@ message AppCompacted {
}
/**
+ * Logs when a Tethering event occurs.
+ *
+ */
+message NetworkTetheringReported {
+ // tethering error code
+ optional android.stats.connectivity.ErrorCode error_code = 1;
+
+ // tethering downstream type
+ optional android.stats.connectivity.DownstreamType downstream_type = 2;
+
+ // transport type of upstream network
+ optional android.stats.connectivity.UpstreamType upstream_type = 3;
+
+ // The user type of Tethering
+ optional android.stats.connectivity.UserType user_type= 4;
+}
+
+/**
* Logs a DNS lookup operation initiated by the system resolver on behalf of an application
* invoking native APIs such as getaddrinfo() or Java APIs such as Network#getAllByName().
*
@@ -10926,6 +10948,114 @@ message MediametricsAudioDeviceConnectionReported {
optional int32 connection_count = 6;
}
+/**
+ * Logs: i) creation of different types of cryptographic keys in the keystore,
+ * ii) operations performed using the keys,
+ * iii) attestation of the keys
+ * Logged from: system/security/keystore/key_event_log_handler.cpp
+ */
+message KeystoreKeyEventReported {
+
+ enum Algorithm {
+ /** Asymmetric algorithms. */
+ RSA = 1;
+ // 2 removed, do not reuse.
+ EC = 3;
+ /** Block cipher algorithms */
+ AES = 32;
+ TRIPLE_DES = 33;
+ /** MAC algorithms */
+ HMAC = 128;
+ };
+ /** Algorithm associated with the key */
+ optional Algorithm algorithm = 1;
+
+ /** Size of the key */
+ optional int32 key_size = 2;
+
+ enum KeyOrigin {
+ /** Generated in keymaster. Should not exist outside the TEE. */
+ GENERATED = 0;
+ /** Derived inside keymaster. Likely exists off-device. */
+ DERIVED = 1;
+ /** Imported into keymaster. Existed as cleartext in Android. */
+ IMPORTED = 2;
+ /** Keymaster did not record origin. */
+ UNKNOWN = 3;
+ /** Securely imported into Keymaster. */
+ SECURELY_IMPORTED = 4;
+ };
+ /* Logs whether the key was generated, imported, securely imported, or derived.*/
+ optional KeyOrigin key_origin = 3;
+
+ enum HardwareAuthenticatorType {
+ NONE = 0;
+ PASSWORD = 1;
+ FINGERPRINT = 2;
+ // Additional entries must be powers of 2.
+ };
+ /**
+ * What auth types does this key require? If none,
+ * then no auth required.
+ */
+ optional HardwareAuthenticatorType user_auth_type = 4;
+
+ /**
+ * If user authentication is required, is the requirement time based? If it
+ * is not time based then this field will not be used and the key is per
+ * operation. Per operation keys must be user authenticated on each usage.
+ */
+ optional int32 user_auth_key_timeout_secs = 5;
+
+ /**
+ * padding mode, digest, block_mode and purpose should ideally be repeated
+ * fields. However, since statsd does not support repeated fields in
+ * pushed atoms, they are represented using bitmaps.
+ */
+
+ /** Track which padding mode is being used.*/
+ optional int32 padding_mode_bitmap = 6;
+
+ /** Track which digest is being used. */
+ optional int32 digest_bitmap = 7;
+
+ /** Track what block mode is being used (for encryption). */
+ optional int32 block_mode_bitmap = 8;
+
+ /** Track what purpose is this key serving. */
+ optional int32 purpose_bitmap = 9;
+
+ enum EcCurve {
+ P_224 = 0;
+ P_256 = 1;
+ P_384 = 2;
+ P_521 = 3;
+ };
+ /** Which ec curve was selected if elliptic curve cryptography is in use **/
+ optional EcCurve ec_curve = 10;
+
+ enum KeyBlobUsageRequirements {
+ STANDALONE = 0;
+ REQUIRES_FILE_SYSTEM = 1;
+ };
+ /** Standalone or is a file system required */
+ optional KeyBlobUsageRequirements key_blob_usage_reqs = 11;
+
+ enum Type {
+ key_operation = 0;
+ key_creation = 1;
+ key_attestation = 2;
+ }
+ /** Key creation event, operation event or attestation event? */
+ optional Type type = 12;
+
+ /** Was the key creation, operation, or attestation successful? */
+ optional bool was_successful = 13;
+
+ /** Response code or error code */
+ optional int32 error_code = 14;
+}
+
// Blob Committer stats
// Keep in sync between:
// frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index 9df4d1f8ce24..bb5d0a6bab58 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -44,7 +44,8 @@ StatsPuller::StatsPuller(const int tagId, const int64_t coolDownNs, const int64_
bool StatsPuller::Pull(const int64_t eventTimeNs, std::vector<std::shared_ptr<LogEvent>>* data) {
lock_guard<std::mutex> lock(mLock);
- int64_t elapsedTimeNs = getElapsedRealtimeNs();
+ const int64_t elapsedTimeNs = getElapsedRealtimeNs();
+ const int64_t systemUptimeMillis = getSystemUptimeMillis();
StatsdStats::getInstance().notePull(mTagId);
const bool shouldUseCache =
(mLastEventTimeNs == eventTimeNs) || (elapsedTimeNs - mLastPullTimeNs < mCoolDownNs);
@@ -67,16 +68,18 @@ bool StatsPuller::Pull(const int64_t eventTimeNs, std::vector<std::shared_ptr<Lo
if (!mHasGoodData) {
return mHasGoodData;
}
- const int64_t pullDurationNs = getElapsedRealtimeNs() - elapsedTimeNs;
- StatsdStats::getInstance().notePullTime(mTagId, pullDurationNs);
- const bool pullTimeOut = pullDurationNs > mPullTimeoutNs;
+ const int64_t pullElapsedDurationNs = getElapsedRealtimeNs() - elapsedTimeNs;
+ const int64_t pullSystemUptimeDurationMillis = getSystemUptimeMillis() - systemUptimeMillis;
+ StatsdStats::getInstance().notePullTime(mTagId, pullElapsedDurationNs);
+ const bool pullTimeOut = pullElapsedDurationNs > mPullTimeoutNs;
if (pullTimeOut) {
// Something went wrong. Discard the data.
mCachedData.clear();
mHasGoodData = false;
- StatsdStats::getInstance().notePullTimeout(mTagId);
+ StatsdStats::getInstance().notePullTimeout(
+ mTagId, pullSystemUptimeDurationMillis, NanoToMillis(pullElapsedDurationNs));
ALOGW("Pull for atom %d exceeds timeout %lld nano seconds.", mTagId,
- (long long)pullDurationNs);
+ (long long)pullElapsedDurationNs);
return mHasGoodData;
}
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index c027fffd20a0..6e89038f4152 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -38,6 +38,7 @@ using android::util::ProtoOutputStream;
using std::lock_guard;
using std::shared_ptr;
using std::string;
+using std::to_string;
using std::vector;
const int FIELD_ID_BEGIN_TIME = 1;
@@ -436,9 +437,18 @@ void StatsdStats::notePullDataError(int pullAtomId) {
mPulledAtomStats[pullAtomId].dataError++;
}
-void StatsdStats::notePullTimeout(int pullAtomId) {
+void StatsdStats::notePullTimeout(int pullAtomId,
+ int64_t pullUptimeMillis,
+ int64_t pullElapsedMillis) {
lock_guard<std::mutex> lock(mLock);
- mPulledAtomStats[pullAtomId].pullTimeout++;
+ PulledAtomStats& pulledAtomStats = mPulledAtomStats[pullAtomId];
+ pulledAtomStats.pullTimeout++;
+
+ if (pulledAtomStats.pullTimeoutMetadata.size() == kMaxTimestampCount) {
+ pulledAtomStats.pullTimeoutMetadata.pop_front();
+ }
+
+ pulledAtomStats.pullTimeoutMetadata.emplace_back(pullUptimeMillis, pullElapsedMillis);
}
void StatsdStats::notePullExceedMaxDelay(int pullAtomId) {
@@ -630,6 +640,7 @@ void StatsdStats::resetInternalLocked() {
pullStats.second.unregisteredCount = 0;
pullStats.second.atomErrorCount = 0;
pullStats.second.binderCallFailCount = 0;
+ pullStats.second.pullTimeoutMetadata.clear();
}
mAtomMetricStats.clear();
mActivationBroadcastGuardrailStats.clear();
@@ -786,6 +797,20 @@ void StatsdStats::dumpStats(int out) const {
pair.second.pullUidProviderNotFound, pair.second.pullerNotFound,
pair.second.registeredCount, pair.second.unregisteredCount,
pair.second.atomErrorCount);
+ if (pair.second.pullTimeoutMetadata.size() > 0) {
+ string uptimeMillis = "(pull timeout system uptime millis) ";
+ string pullTimeoutMillis = "(pull timeout elapsed time millis) ";
+ for (const auto& stats : pair.second.pullTimeoutMetadata) {
+ uptimeMillis.append(to_string(stats.pullTimeoutUptimeMillis)).append(",");;
+ pullTimeoutMillis.append(to_string(stats.pullTimeoutElapsedMillis)).append(",");
+ }
+ uptimeMillis.pop_back();
+ uptimeMillis.push_back('\n');
+ pullTimeoutMillis.pop_back();
+ pullTimeoutMillis.push_back('\n');
+ dprintf(out, "%s", uptimeMillis.c_str());
+ dprintf(out, "%s", pullTimeoutMillis.c_str());
+ }
}
if (mAnomalyAlarmRegisteredStats > 0) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 9d46dcea1896..005048446fc3 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -352,7 +352,7 @@ public:
/*
* Records pull exceeds timeout for the puller.
*/
- void notePullTimeout(int pullAtomId);
+ void notePullTimeout(int pullAtomId, int64_t pullUptimeMillis, int64_t pullElapsedMillis);
/*
* Records pull exceeds max delay for a metric.
@@ -498,6 +498,14 @@ public:
*/
void dumpStats(int outFd) const;
+ typedef struct PullTimeoutMetadata {
+ int64_t pullTimeoutUptimeMillis;
+ int64_t pullTimeoutElapsedMillis;
+ PullTimeoutMetadata(int64_t uptimeMillis, int64_t elapsedMillis) :
+ pullTimeoutUptimeMillis(uptimeMillis),
+ pullTimeoutElapsedMillis(elapsedMillis) {/* do nothing */}
+ } PullTimeoutMetadata;
+
typedef struct {
long totalPull = 0;
long totalPullFromCache = 0;
@@ -519,6 +527,7 @@ public:
long unregisteredCount = 0;
int32_t atomErrorCount = 0;
long binderCallFailCount = 0;
+ std::list<PullTimeoutMetadata> pullTimeoutMetadata;
} PulledAtomStats;
typedef struct {
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 6bfa26761b2f..ddd2725c9cb9 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -467,6 +467,11 @@ message StatsdStatsReport {
optional int64 binder_call_failed = 19;
optional int64 failed_uid_provider_not_found = 20;
optional int64 puller_not_found = 21;
+ message PullTimeoutMetadata {
+ optional int64 pull_timeout_uptime_millis = 1;
+ optional int64 pull_timeout_elapsed_millis = 2;
+ }
+ repeated PullTimeoutMetadata pull_atom_metadata = 22;
}
repeated PulledAtomStats pulled_atom_stats = 10;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index bafdfcba59b2..423bae8bc0a4 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -81,6 +81,9 @@ const int FIELD_ID_ATOM_ERROR_COUNT = 18;
const int FIELD_ID_BINDER_CALL_FAIL_COUNT = 19;
const int FIELD_ID_PULL_UID_PROVIDER_NOT_FOUND = 20;
const int FIELD_ID_PULLER_NOT_FOUND = 21;
+const int FIELD_ID_PULL_TIMEOUT_METADATA = 22;
+const int FIELD_ID_PULL_TIMEOUT_METADATA_UPTIME_MILLIS = 1;
+const int FIELD_ID_PULL_TIMEOUT_METADATA_ELAPSED_MILLIS = 2;
// for AtomMetricStats proto
const int FIELD_ID_ATOM_METRIC_STATS = 17;
@@ -497,6 +500,16 @@ void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>
(long long)pair.second.pullUidProviderNotFound);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULLER_NOT_FOUND,
(long long)pair.second.pullerNotFound);
+ for (const auto& pullTimeoutMetadata : pair.second.pullTimeoutMetadata) {
+ uint64_t timeoutMetadataToken = protoOutput->start(FIELD_TYPE_MESSAGE |
+ FIELD_ID_PULL_TIMEOUT_METADATA |
+ FIELD_COUNT_REPEATED);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_TIMEOUT_METADATA_UPTIME_MILLIS,
+ pullTimeoutMetadata.pullTimeoutUptimeMillis);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_TIMEOUT_METADATA_ELAPSED_MILLIS,
+ pullTimeoutMetadata.pullTimeoutElapsedMillis);
+ protoOutput->end(timeoutMetadataToken);
+ }
protoOutput->end(token);
}
@@ -542,6 +555,10 @@ int64_t getElapsedRealtimeMillis() {
return ::android::elapsedRealtime();
}
+int64_t getSystemUptimeMillis() {
+ return ::android::uptimeMillis();
+}
+
int64_t getWallClockNs() {
return time(nullptr) * NS_PER_SEC;
}
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index 20d93b5a5365..eb65dc6979c5 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -61,6 +61,9 @@ int64_t getElapsedRealtimeMillis();
// Gets the elapsed timestamp in seconds.
int64_t getElapsedRealtimeSec();
+// Gets the system uptime in millis.
+int64_t getSystemUptimeMillis();
+
// Gets the wall clock timestamp in ns.
int64_t getWallClockNs();
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 5cc10cd9840c..428c46f8a0d2 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -306,6 +306,8 @@ TEST(StatsdStatsTest, TestPullAtomStats) {
stats.notePullUidProviderNotFound(util::DISK_SPACE);
stats.notePullerNotFound(util::DISK_SPACE);
stats.notePullerNotFound(util::DISK_SPACE);
+ stats.notePullTimeout(util::DISK_SPACE, 3000L, 6000L);
+ stats.notePullTimeout(util::DISK_SPACE, 4000L, 7000L);
vector<uint8_t> output;
stats.dumpStats(&output, false);
@@ -328,6 +330,13 @@ TEST(StatsdStatsTest, TestPullAtomStats) {
EXPECT_EQ(1L, report.pulled_atom_stats(0).binder_call_failed());
EXPECT_EQ(1L, report.pulled_atom_stats(0).failed_uid_provider_not_found());
EXPECT_EQ(2L, report.pulled_atom_stats(0).puller_not_found());
+ ASSERT_EQ(2, report.pulled_atom_stats(0).pull_atom_metadata_size());
+ EXPECT_EQ(3000L, report.pulled_atom_stats(0).pull_atom_metadata(0).pull_timeout_uptime_millis());
+ EXPECT_EQ(4000L, report.pulled_atom_stats(0).pull_atom_metadata(1).pull_timeout_uptime_millis());
+ EXPECT_EQ(6000L, report.pulled_atom_stats(0).pull_atom_metadata(0)
+ .pull_timeout_elapsed_millis());
+ EXPECT_EQ(7000L, report.pulled_atom_stats(0).pull_atom_metadata(1)
+ .pull_timeout_elapsed_millis());
}
TEST(StatsdStatsTest, TestAtomMetricsStats) {
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 1cc63da3db0a..0f31529451fb 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -433,13 +433,21 @@ public class ActivityTaskManager {
}
}
- /** Returns whether the current UI mode supports error dialogs (ANR, crash, etc). */
- public static boolean currentUiModeSupportsErrorDialogs(@NonNull Context context) {
- final Configuration config = context.getResources().getConfiguration();
+ /**
+ * @return whether the UI mode of the given config supports error dialogs (ANR, crash, etc).
+ * @hide
+ */
+ public static boolean currentUiModeSupportsErrorDialogs(@NonNull Configuration config) {
int modeType = config.uiMode & Configuration.UI_MODE_TYPE_MASK;
return (modeType != Configuration.UI_MODE_TYPE_CAR
&& !(modeType == Configuration.UI_MODE_TYPE_WATCH && Build.IS_USER)
&& modeType != Configuration.UI_MODE_TYPE_TELEVISION
&& modeType != Configuration.UI_MODE_TYPE_VR_HEADSET);
}
+
+ /** @return whether the current UI mode supports error dialogs (ANR, crash, etc). */
+ public static boolean currentUiModeSupportsErrorDialogs(@NonNull Context context) {
+ final Configuration config = context.getResources().getConfiguration();
+ return currentUiModeSupportsErrorDialogs(config);
+ }
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 71b866b7b16a..3347e045886a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -227,7 +227,7 @@ public class AppOpsManager {
* {@link #sMessageCollector}, which forces {@link COLLECT_SYNC} mode.
*/
@GuardedBy("sLock")
- private static ArrayList<SyncNotedAppOp> sUnforwardedOps = new ArrayList<>();
+ private static ArrayList<AsyncNotedAppOp> sUnforwardedOps = new ArrayList<>();
/**
* Additional collector that collect accesses and forwards a few of them them via
@@ -8195,7 +8195,10 @@ public class AppOpsManager {
if (sOnOpNotedCallback != null) {
sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code, attributionTag));
} else {
- sUnforwardedOps.add(new SyncNotedAppOp(code, attributionTag));
+ String message = getFormattedStackTrace();
+ sUnforwardedOps.add(
+ new AsyncNotedAppOp(code, Process.myUid(), attributionTag,
+ message, System.currentTimeMillis()));
if (sUnforwardedOps.size() > MAX_UNFORWARDED_OPS) {
sUnforwardedOps.remove(0);
}
@@ -8268,10 +8271,10 @@ public class AppOpsManager {
synchronized (this) {
int numMissedSyncOps = sUnforwardedOps.size();
for (int i = 0; i < numMissedSyncOps; i++) {
- final SyncNotedAppOp syncNotedAppOp = sUnforwardedOps.get(i);
+ final AsyncNotedAppOp syncNotedAppOp = sUnforwardedOps.get(i);
if (sOnOpNotedCallback != null) {
sOnOpNotedCallback.getAsyncNotedExecutor().execute(
- () -> sOnOpNotedCallback.onNoted(syncNotedAppOp));
+ () -> sOnOpNotedCallback.onAsyncNoted(syncNotedAppOp));
}
}
sUnforwardedOps.clear();
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index c7a2a1e11c9e..f3f00e50715b 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -16,8 +16,6 @@
package android.app;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -170,6 +168,14 @@ public class TaskInfo {
@Nullable
public ActivityInfo topActivityInfo;
+ /**
+ * Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity
+ * supports), this is what the system actually uses for resizability based on other policy and
+ * developer options.
+ * @hide
+ */
+ public boolean isResizeable;
+
TaskInfo() {
// Do nothing
}
@@ -193,11 +199,6 @@ public class TaskInfo {
}
/** @hide */
- public boolean isResizable() {
- return resizeMode != RESIZE_MODE_UNRESIZEABLE;
- }
-
- /** @hide */
@NonNull
@TestApi
public WindowContainerToken getToken() {
@@ -245,6 +246,7 @@ public class TaskInfo {
topActivityInfo = source.readInt() != 0
? ActivityInfo.CREATOR.createFromParcel(source)
: null;
+ isResizeable = source.readBoolean();
}
/**
@@ -294,6 +296,7 @@ public class TaskInfo {
dest.writeInt(1);
topActivityInfo.writeToParcel(dest, flags);
}
+ dest.writeBoolean(isResizeable);
}
@Override
@@ -308,6 +311,7 @@ public class TaskInfo {
+ " lastActiveTime=" + lastActiveTime
+ " supportsSplitScreenMultiWindow=" + supportsSplitScreenMultiWindow
+ " resizeMode=" + resizeMode
+ + " isResizeable=" + isResizeable
+ " token=" + token
+ " topActivityType=" + topActivityType
+ " pictureInPictureParams=" + pictureInPictureParams
diff --git a/core/java/android/app/admin/DevicePolicyCache.java b/core/java/android/app/admin/DevicePolicyCache.java
index 4d9970c2c144..15ff531b445d 100644
--- a/core/java/android/app/admin/DevicePolicyCache.java
+++ b/core/java/android/app/admin/DevicePolicyCache.java
@@ -41,7 +41,8 @@ public abstract class DevicePolicyCache {
/**
* See {@link DevicePolicyManager#getScreenCaptureDisabled}
*/
- public abstract boolean getScreenCaptureDisabled(@UserIdInt int userHandle);
+ public abstract boolean isScreenCaptureAllowed(@UserIdInt int userHandle,
+ boolean ownerCanAddInternalSystemWindow);
/**
* Caches {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} of the
@@ -56,8 +57,9 @@ public abstract class DevicePolicyCache {
private static final EmptyDevicePolicyCache INSTANCE = new EmptyDevicePolicyCache();
@Override
- public boolean getScreenCaptureDisabled(int userHandle) {
- return false;
+ public boolean isScreenCaptureAllowed(int userHandle,
+ boolean ownerCanAddInternalSystemWindow) {
+ return true;
}
@Override
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 24be45cb20fe..8e687413b7e1 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -51,13 +51,6 @@ public class BluetoothDeviceFilterUtils {
return s == null ? null : Pattern.compile(s);
}
- static boolean matches(ScanFilter filter, BluetoothDevice device) {
- boolean result = matchesAddress(filter.getDeviceAddress(), device)
- && matchesServiceUuid(filter.getServiceUuid(), filter.getServiceUuidMask(), device);
- if (DEBUG) debugLogMatchResult(result, device, filter);
- return result;
- }
-
static boolean matchesAddress(String deviceAddress, BluetoothDevice device) {
final boolean result = deviceAddress == null
|| (device != null && deviceAddress.equals(device.getAddress()));
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index dccfb0346c9c..8c071fe99104 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -37,7 +37,6 @@ import android.util.Log;
import com.android.internal.util.BitUtils;
import com.android.internal.util.ObjectUtils;
-import com.android.internal.util.Preconditions;
import libcore.util.HexEncoding;
@@ -166,21 +165,18 @@ public final class BluetoothLeDeviceFilter implements DeviceFilter<ScanResult> {
/** @hide */
@Override
- public boolean matches(ScanResult device) {
- boolean result = matches(device.getDevice())
+ public boolean matches(ScanResult scanResult) {
+ BluetoothDevice device = scanResult.getDevice();
+ boolean result = getScanFilter().matches(scanResult)
+ && BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device)
&& (mRawDataFilter == null
- || BitUtils.maskedEquals(device.getScanRecord().getBytes(),
+ || BitUtils.maskedEquals(scanResult.getScanRecord().getBytes(),
mRawDataFilter, mRawDataFilterMask));
if (DEBUG) Log.i(LOG_TAG, "matches(this = " + this + ", device = " + device +
") -> " + result);
return result;
}
- private boolean matches(BluetoothDevice device) {
- return BluetoothDeviceFilterUtils.matches(getScanFilter(), device)
- && BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device);
- }
-
/** @hide */
@Override
public int getMediumType() {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index be3cfeff729e..ededd0d2ea30 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6445,7 +6445,7 @@ public class Intent implements Parcelable, Cloneable {
public static final int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 0x00002000;
/**
- * This flag is only used in split-screen multi-window mode. The new activity will be displayed
+ * This flag is only used for split-screen multi-window mode. The new activity will be displayed
* adjacent to the one launching it. This can only be used in conjunction with
* {@link #FLAG_ACTIVITY_NEW_TASK}. Also, setting {@link #FLAG_ACTIVITY_MULTIPLE_TASK} is
* required if you want a new instance of an existing activity to be created.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 885ffbac3d30..70e4e6cbf622 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1377,9 +1377,11 @@ public class PackageParser {
}
SigningDetails verified;
if (skipVerify) {
- // systemDir APKs are already trusted, save time by not verifying
+ // systemDir APKs are already trusted, save time by not verifying; since the signature
+ // is not verified and some system apps can have their V2+ signatures stripped allow
+ // pulling the certs from the jar signature.
verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
- apkPath, minSignatureScheme);
+ apkPath, SigningDetails.SignatureSchemeVersion.JAR);
} else {
verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 317107829623..bc9c71e7a68e 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -2748,9 +2748,11 @@ public class ParsingPackageUtils {
SigningDetails verified;
try {
if (skipVerify) {
- // systemDir APKs are already trusted, save time by not verifying
+ // systemDir APKs are already trusted, save time by not verifying; since the
+ // signature is not verified and some system apps can have their V2+ signatures
+ // stripped allow pulling the certs from the jar signature.
verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
- baseCodePath, minSignatureScheme);
+ baseCodePath, SigningDetails.SignatureSchemeVersion.JAR);
} else {
verified = ApkSignatureVerifier.verify(baseCodePath, minSignatureScheme);
}
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index aa75f6042db8..53fdf38101bc 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -952,19 +952,35 @@ public abstract class CameraMetadata<TKey> {
* <li>{@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference}</li>
* <li>{@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion}</li>
* </ul>
- * <p>The field of view of all non-RAW physical streams must be the same or as close as
- * possible to that of non-RAW logical streams. If the requested FOV is outside of the
- * range supported by the physical camera, the physical stream for that physical camera
- * will use either the maximum or minimum scaler crop region, depending on which one is
- * closer to the requested FOV. For example, for a logical camera with wide-tele lens
- * configuration where the wide lens is the default, if the logical camera's crop region
- * is set to maximum, the physical stream for the tele lens will be configured to its
- * maximum crop region. On the other hand, if the logical camera has a normal-wide lens
- * configuration where the normal lens is the default, when the logical camera's crop
- * region is set to maximum, the FOV of the logical streams will be that of the normal
- * lens. The FOV of the physical streams for the wide 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>The field of view of non-RAW physical streams must not be smaller than that of the
+ * non-RAW logical streams, or the maximum field-of-view of the physical camera,
+ * whichever is smaller. The application should check the physical capture result
+ * metadata for how the physical streams are cropped or zoomed. More specifically, given
+ * the physical camera result metadata, the effective horizontal field-of-view of the
+ * physical camera is:</p>
+ * <pre><code>fov = 2 * atan2(cropW * sensorW / (2 * zoomRatio * activeArrayW), focalLength)
+ * </code></pre>
+ * <p>where the equation parameters are the physical camera's crop region width, physical
+ * sensor width, zoom ratio, active array width, and focal length respectively. Typically
+ * the physical stream of active physical camera has the same field-of-view as the
+ * logical streams. However, the same may not be true for physical streams from
+ * non-active physical cameras. For example, if the logical camera has a wide-ultrawide
+ * configuration where the wide lens is the default, when the crop region is set to the
+ * logical camera's active array size, (and the zoom ratio set to 1.0 starting from
+ * Android 11), a physical stream for the ultrawide camera may prefer outputing images
+ * with larger field-of-view than that of the wide camera for better stereo matching
+ * margin or more robust motion tracking. At the same time, the physical non-RAW streams'
+ * field of view must not be smaller than the requested crop region and zoom ratio, as
+ * long as it's within the physical lens' capability. For example, for a logical camera
+ * with wide-tele lens configuration where the wide lens is the default, if the logical
+ * camera's crop region is set to maximum size, and zoom ratio set to 1.0, the physical
+ * stream for the tele lens will be configured to its maximum size crop region (no zoom).</p>
+ * <p><em>Deprecated:</em> Prior to Android 11, the field of view of all non-RAW physical streams
+ * cannot be larger than that of non-RAW logical streams. If the logical camera has a
+ * wide-ultrawide lens configuration where the wide lens is the default, when the logical
+ * 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>Even if the underlying physical cameras have different RAW characteristics (such as
* size or CFA pattern), a logical camera can still advertise RAW capability. In this
* case, when the application configures a RAW stream, the camera device will make sure
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 6d49add65c5b..e21b45ab6577 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1072,7 +1072,7 @@ public class CameraDeviceImpl extends CameraDevice
* @param lastFrameNumber last frame number returned from binder.
* @param repeatingRequestTypes the repeating requests' types.
*/
- private void checkEarlyTriggerSequenceComplete(
+ private void checkEarlyTriggerSequenceCompleteLocked(
final int requestId, final long lastFrameNumber,
final int[] repeatingRequestTypes) {
// lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
@@ -1154,7 +1154,6 @@ public class CameraDeviceImpl extends CameraDevice
checkIfCameraClosedOrInError();
// Make sure that there all requests have at least 1 surface; all surfaces are non-null;
- // the surface isn't a physical stream surface for reprocessing request
for (CaptureRequest request : requestList) {
if (request.getTargets().isEmpty()) {
throw new IllegalArgumentException(
@@ -1165,17 +1164,6 @@ public class CameraDeviceImpl extends CameraDevice
if (surface == null) {
throw new IllegalArgumentException("Null Surface targets are not allowed");
}
-
- for (int i = 0; i < mConfiguredOutputs.size(); i++) {
- OutputConfiguration configuration = mConfiguredOutputs.valueAt(i);
- if (configuration.isForPhysicalCamera()
- && configuration.getSurfaces().contains(surface)) {
- if (request.isReprocess()) {
- throw new IllegalArgumentException(
- "Reprocess request on physical stream is not allowed");
- }
- }
- }
}
}
@@ -1212,7 +1200,7 @@ public class CameraDeviceImpl extends CameraDevice
if (repeating) {
if (mRepeatingRequestId != REQUEST_ID_NONE) {
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId,
+ checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId,
requestInfo.getLastFrameNumber(),
mRepeatingRequestTypes);
}
@@ -1269,7 +1257,7 @@ public class CameraDeviceImpl extends CameraDevice
return;
}
- checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber, requestTypes);
+ checkEarlyTriggerSequenceCompleteLocked(requestId, lastFrameNumber, requestTypes);
}
}
}
@@ -1302,7 +1290,7 @@ public class CameraDeviceImpl extends CameraDevice
long lastFrameNumber = mRemoteDevice.flush();
if (mRepeatingRequestId != REQUEST_ID_NONE) {
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber,
+ checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId, lastFrameNumber,
mRepeatingRequestTypes);
mRepeatingRequestId = REQUEST_ID_NONE;
mRepeatingRequestTypes = null;
@@ -1442,78 +1430,137 @@ public class CameraDeviceImpl extends CameraDevice
long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
long completedZslStillFrameNumber = mFrameNumberTracker.getCompletedZslStillFrameNumber();
- boolean isReprocess = false;
+
Iterator<RequestLastFrameNumbersHolder> iter = mRequestLastFrameNumbersList.iterator();
while (iter.hasNext()) {
final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
- boolean sequenceCompleted = false;
final int requestId = requestLastFrameNumbers.getRequestId();
final CaptureCallbackHolder holder;
- synchronized(mInterfaceLock) {
- if (mRemoteDevice == null) {
- Log.w(TAG, "Camera closed while checking sequences");
- return;
+ if (mRemoteDevice == null) {
+ Log.w(TAG, "Camera closed while checking sequences");
+ return;
+ }
+ if (!requestLastFrameNumbers.isSequenceCompleted()) {
+ long lastRegularFrameNumber =
+ requestLastFrameNumbers.getLastRegularFrameNumber();
+ long lastReprocessFrameNumber =
+ requestLastFrameNumbers.getLastReprocessFrameNumber();
+ long lastZslStillFrameNumber =
+ requestLastFrameNumbers.getLastZslStillFrameNumber();
+ if (lastRegularFrameNumber <= completedFrameNumber
+ && lastReprocessFrameNumber <= completedReprocessFrameNumber
+ && lastZslStillFrameNumber <= completedZslStillFrameNumber) {
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Mark requestId %d as completed, because lastRegularFrame %d "
+ + "is <= %d, lastReprocessFrame %d is <= %d, "
+ + "lastZslStillFrame %d is <= %d", requestId,
+ lastRegularFrameNumber, completedFrameNumber,
+ lastReprocessFrameNumber, completedReprocessFrameNumber,
+ lastZslStillFrameNumber, completedZslStillFrameNumber));
+ }
+ requestLastFrameNumbers.markSequenceCompleted();
}
+ // Call onCaptureSequenceCompleted
int index = mCaptureCallbackMap.indexOfKey(requestId);
holder = (index >= 0) ?
mCaptureCallbackMap.valueAt(index) : null;
- if (holder != null) {
- long lastRegularFrameNumber =
- requestLastFrameNumbers.getLastRegularFrameNumber();
- long lastReprocessFrameNumber =
- requestLastFrameNumbers.getLastReprocessFrameNumber();
- long lastZslStillFrameNumber =
- requestLastFrameNumbers.getLastZslStillFrameNumber();
- // check if it's okay to remove request from mCaptureCallbackMap
- if (lastRegularFrameNumber <= completedFrameNumber
- && lastReprocessFrameNumber <= completedReprocessFrameNumber
- && lastZslStillFrameNumber <= completedZslStillFrameNumber) {
- sequenceCompleted = true;
- mCaptureCallbackMap.removeAt(index);
- if (DEBUG) {
- Log.v(TAG, String.format(
- "Remove holder for requestId %d, because lastRegularFrame %d "
- + "is <= %d, lastReprocessFrame %d is <= %d, "
- + "lastZslStillFrame %d is <= %d", requestId,
- lastRegularFrameNumber, completedFrameNumber,
- lastReprocessFrameNumber, completedReprocessFrameNumber,
- lastZslStillFrameNumber, completedZslStillFrameNumber));
+ if (holder != null && requestLastFrameNumbers.isSequenceCompleted()) {
+ Runnable resultDispatch = new Runnable() {
+ @Override
+ public void run() {
+ if (!CameraDeviceImpl.this.isClosed()){
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "fire sequence complete for request %d",
+ requestId));
+ }
+
+ holder.getCallback().onCaptureSequenceCompleted(
+ CameraDeviceImpl.this,
+ requestId,
+ requestLastFrameNumbers.getLastFrameNumber());
+ }
}
+ };
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ holder.getExecutor().execute(resultDispatch);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
}
- // If no callback is registered for this requestId or sequence completed, remove it
- // from the frame number->request pair because it's not needed anymore.
- if (holder == null || sequenceCompleted) {
+ if (requestLastFrameNumbers.isSequenceCompleted() &&
+ requestLastFrameNumbers.isInflightCompleted()) {
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ if (index >= 0) {
+ mCaptureCallbackMap.removeAt(index);
+ }
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Remove holder for requestId %d", requestId));
+ }
iter.remove();
}
+ }
+ }
- // Call onCaptureSequenceCompleted
- if (sequenceCompleted) {
- Runnable resultDispatch = new Runnable() {
- @Override
- public void run() {
- if (!CameraDeviceImpl.this.isClosed()){
- if (DEBUG) {
- Log.d(TAG, String.format(
- "fire sequence complete for request %d",
- requestId));
- }
+ private void removeCompletedCallbackHolderLocked(long lastCompletedRegularFrameNumber,
+ long lastCompletedReprocessFrameNumber, long lastCompletedZslStillFrameNumber) {
+ if (DEBUG) {
+ Log.v(TAG, String.format("remove completed callback holders for "
+ + "lastCompletedRegularFrameNumber %d, "
+ + "lastCompletedReprocessFrameNumber %d, "
+ + "lastCompletedZslStillFrameNumber %d",
+ lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber,
+ lastCompletedZslStillFrameNumber));
+ }
- holder.getCallback().onCaptureSequenceCompleted(
- CameraDeviceImpl.this,
- requestId,
- requestLastFrameNumbers.getLastFrameNumber());
- }
+ Iterator<RequestLastFrameNumbersHolder> iter = mRequestLastFrameNumbersList.iterator();
+ while (iter.hasNext()) {
+ final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
+ final int requestId = requestLastFrameNumbers.getRequestId();
+ final CaptureCallbackHolder holder;
+ if (mRemoteDevice == null) {
+ Log.w(TAG, "Camera closed while removing completed callback holders");
+ return;
+ }
+
+ long lastRegularFrameNumber =
+ requestLastFrameNumbers.getLastRegularFrameNumber();
+ long lastReprocessFrameNumber =
+ requestLastFrameNumbers.getLastReprocessFrameNumber();
+ long lastZslStillFrameNumber =
+ requestLastFrameNumbers.getLastZslStillFrameNumber();
+
+ if (lastRegularFrameNumber <= lastCompletedRegularFrameNumber
+ && lastReprocessFrameNumber <= lastCompletedReprocessFrameNumber
+ && lastZslStillFrameNumber <= lastCompletedZslStillFrameNumber) {
+
+ if (requestLastFrameNumbers.isSequenceCompleted()) {
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ if (index >= 0) {
+ mCaptureCallbackMap.removeAt(index);
}
- };
- final long ident = Binder.clearCallingIdentity();
- try {
- holder.getExecutor().execute(resultDispatch);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Remove holder for requestId %d, because lastRegularFrame %d "
+ + "is <= %d, lastReprocessFrame %d is <= %d, "
+ + "lastZslStillFrame %d is <= %d", requestId,
+ lastRegularFrameNumber, lastCompletedRegularFrameNumber,
+ lastReprocessFrameNumber, lastCompletedReprocessFrameNumber,
+ lastZslStillFrameNumber, lastCompletedZslStillFrameNumber));
+ }
+ iter.remove();
+ } else {
+ if (DEBUG) {
+ Log.v(TAG, "Sequence not yet completed for request id " + requestId);
+ }
+ requestLastFrameNumbers.markInflightCompleted();
}
}
}
@@ -1702,6 +1749,12 @@ public class CameraDeviceImpl extends CameraDevice
return;
}
+ // Remove all capture callbacks now that device has gone to IDLE state.
+ removeCompletedCallbackHolderLocked(
+ Long.MAX_VALUE, /*lastCompletedRegularFrameNumber*/
+ Long.MAX_VALUE, /*lastCompletedReprocessFrameNumber*/
+ Long.MAX_VALUE /*lastCompletedZslStillFrameNumber*/);
+
if (!CameraDeviceImpl.this.mIdle) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -1747,7 +1800,7 @@ public class CameraDeviceImpl extends CameraDevice
return;
}
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber,
+ checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId, lastFrameNumber,
mRepeatingRequestTypes);
// Check if there is already a new repeating request
if (mRepeatingRequestId == repeatingRequestId) {
@@ -1766,9 +1819,18 @@ public class CameraDeviceImpl extends CameraDevice
public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
int requestId = resultExtras.getRequestId();
final long frameNumber = resultExtras.getFrameNumber();
+ final long lastCompletedRegularFrameNumber =
+ resultExtras.getLastCompletedRegularFrameNumber();
+ final long lastCompletedReprocessFrameNumber =
+ resultExtras.getLastCompletedReprocessFrameNumber();
+ final long lastCompletedZslFrameNumber =
+ resultExtras.getLastCompletedZslFrameNumber();
if (DEBUG) {
- Log.d(TAG, "Capture started for id " + requestId + " frame number " + frameNumber);
+ Log.d(TAG, "Capture started for id " + requestId + " frame number " + frameNumber
+ + ": completedRegularFrameNumber " + lastCompletedRegularFrameNumber
+ + ", completedReprocessFrameNUmber " + lastCompletedReprocessFrameNumber
+ + ", completedZslFrameNumber " + lastCompletedZslFrameNumber);
}
final CaptureCallbackHolder holder;
@@ -1784,6 +1846,12 @@ public class CameraDeviceImpl extends CameraDevice
return;
}
+ // Check if it's okay to remove completed callbacks from mCaptureCallbackMap.
+ // A callback is completed if the corresponding inflight request has been removed
+ // from the inflight queue in cameraservice.
+ removeCompletedCallbackHolderLocked(lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber, lastCompletedZslFrameNumber);
+
// Get the callback for this frame ID, if there is one
holder = CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
diff --git a/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
index 1d9d644c9306..413caf5e22e0 100644
--- a/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
@@ -182,6 +182,12 @@ public class CameraOfflineSessionImpl extends CameraOfflineSession
return;
}
+ // Remove all capture callbacks now that device has gone to IDLE state.
+ removeCompletedCallbackHolderLocked(
+ Long.MAX_VALUE, /*lastCompletedRegularFrameNumber*/
+ Long.MAX_VALUE, /*lastCompletedReprocessFrameNumber*/
+ Long.MAX_VALUE /*lastCompletedZslStillFrameNumber*/);
+
Runnable idleDispatch = new Runnable() {
@Override
public void run() {
@@ -204,10 +210,22 @@ public class CameraOfflineSessionImpl extends CameraOfflineSession
public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
int requestId = resultExtras.getRequestId();
final long frameNumber = resultExtras.getFrameNumber();
+ final long lastCompletedRegularFrameNumber =
+ resultExtras.getLastCompletedRegularFrameNumber();
+ final long lastCompletedReprocessFrameNumber =
+ resultExtras.getLastCompletedReprocessFrameNumber();
+ final long lastCompletedZslFrameNumber =
+ resultExtras.getLastCompletedZslFrameNumber();
final CaptureCallbackHolder holder;
synchronized(mInterfaceLock) {
+ // Check if it's okay to remove completed callbacks from mCaptureCallbackMap.
+ // A callback is completed if the corresponding inflight request has been removed
+ // from the inflight queue in cameraservice.
+ removeCompletedCallbackHolderLocked(lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber, lastCompletedZslFrameNumber);
+
// Get the callback for this frame ID, if there is one
holder = CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);
@@ -601,6 +619,61 @@ public class CameraOfflineSessionImpl extends CameraOfflineSession
}
}
+ private void removeCompletedCallbackHolderLocked(long lastCompletedRegularFrameNumber,
+ long lastCompletedReprocessFrameNumber, long lastCompletedZslStillFrameNumber) {
+ if (DEBUG) {
+ Log.v(TAG, String.format("remove completed callback holders for "
+ + "lastCompletedRegularFrameNumber %d, "
+ + "lastCompletedReprocessFrameNumber %d, "
+ + "lastCompletedZslStillFrameNumber %d",
+ lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber,
+ lastCompletedZslStillFrameNumber));
+ }
+
+ boolean isReprocess = false;
+ Iterator<RequestLastFrameNumbersHolder> iter =
+ mOfflineRequestLastFrameNumbersList.iterator();
+ while (iter.hasNext()) {
+ final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
+ final int requestId = requestLastFrameNumbers.getRequestId();
+ final CaptureCallbackHolder holder;
+
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ holder = (index >= 0) ?
+ mCaptureCallbackMap.valueAt(index) : null;
+ if (holder != null) {
+ long lastRegularFrameNumber =
+ requestLastFrameNumbers.getLastRegularFrameNumber();
+ long lastReprocessFrameNumber =
+ requestLastFrameNumbers.getLastReprocessFrameNumber();
+ long lastZslStillFrameNumber =
+ requestLastFrameNumbers.getLastZslStillFrameNumber();
+ if (lastRegularFrameNumber <= lastCompletedRegularFrameNumber
+ && lastReprocessFrameNumber <= lastCompletedReprocessFrameNumber
+ && lastZslStillFrameNumber <= lastCompletedZslStillFrameNumber) {
+ if (requestLastFrameNumbers.isSequenceCompleted()) {
+ mCaptureCallbackMap.removeAt(index);
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Remove holder for requestId %d, because lastRegularFrame %d "
+ + "is <= %d, lastReprocessFrame %d is <= %d, "
+ + "lastZslStillFrame %d is <= %d", requestId,
+ lastRegularFrameNumber, lastCompletedRegularFrameNumber,
+ lastReprocessFrameNumber, lastCompletedReprocessFrameNumber,
+ lastZslStillFrameNumber, lastCompletedZslStillFrameNumber));
+ }
+
+ iter.remove();
+ } else {
+ Log.e(TAG, "Sequence not yet completed for request id " + requestId);
+ continue;
+ }
+ }
+ }
+ }
+ }
+
public void notifyFailedSwitch() {
synchronized(mInterfaceLock) {
Runnable switchFailDispatch = new Runnable() {
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
index 1ff5bd562f2e..5d9da73fd5c0 100644
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
+++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
@@ -30,6 +30,9 @@ public class CaptureResultExtras implements Parcelable {
private int partialResultCount;
private int errorStreamId;
private String errorPhysicalCameraId;
+ private long lastCompletedRegularFrameNumber;
+ private long lastCompletedReprocessFrameNumber;
+ private long lastCompletedZslFrameNumber;
public static final @android.annotation.NonNull Parcelable.Creator<CaptureResultExtras> CREATOR =
new Parcelable.Creator<CaptureResultExtras>() {
@@ -51,7 +54,9 @@ public class CaptureResultExtras implements Parcelable {
public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId,
int precaptureTriggerId, long frameNumber,
int partialResultCount, int errorStreamId,
- String errorPhysicalCameraId) {
+ String errorPhysicalCameraId, long lastCompletedRegularFrameNumber,
+ long lastCompletedReprocessFrameNumber,
+ long lastCompletedZslFrameNumber) {
this.requestId = requestId;
this.subsequenceId = subsequenceId;
this.afTriggerId = afTriggerId;
@@ -60,6 +65,9 @@ public class CaptureResultExtras implements Parcelable {
this.partialResultCount = partialResultCount;
this.errorStreamId = errorStreamId;
this.errorPhysicalCameraId = errorPhysicalCameraId;
+ this.lastCompletedRegularFrameNumber = lastCompletedRegularFrameNumber;
+ this.lastCompletedReprocessFrameNumber = lastCompletedReprocessFrameNumber;
+ this.lastCompletedZslFrameNumber = lastCompletedZslFrameNumber;
}
@Override
@@ -82,6 +90,9 @@ public class CaptureResultExtras implements Parcelable {
} else {
dest.writeBoolean(false);
}
+ dest.writeLong(lastCompletedRegularFrameNumber);
+ dest.writeLong(lastCompletedReprocessFrameNumber);
+ dest.writeLong(lastCompletedZslFrameNumber);
}
public void readFromParcel(Parcel in) {
@@ -96,6 +107,9 @@ public class CaptureResultExtras implements Parcelable {
if (errorPhysicalCameraIdPresent) {
errorPhysicalCameraId = in.readString();
}
+ lastCompletedRegularFrameNumber = in.readLong();
+ lastCompletedReprocessFrameNumber = in.readLong();
+ lastCompletedZslFrameNumber = in.readLong();
}
public String getErrorPhysicalCameraId() {
@@ -129,4 +143,16 @@ public class CaptureResultExtras implements Parcelable {
public int getErrorStreamId() {
return errorStreamId;
}
+
+ public long getLastCompletedRegularFrameNumber() {
+ return lastCompletedRegularFrameNumber;
+ }
+
+ public long getLastCompletedReprocessFrameNumber() {
+ return lastCompletedReprocessFrameNumber;
+ }
+
+ public long getLastCompletedZslFrameNumber() {
+ return lastCompletedZslFrameNumber;
+ }
}
diff --git a/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java b/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
index bd1df9e1ac7d..0ee4ebc1aa87 100644
--- a/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
+++ b/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
@@ -38,6 +38,10 @@ public class RequestLastFrameNumbersHolder {
// The last ZSL still capture frame number for this request ID. It's
// CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no zsl request.
private final long mLastZslStillFrameNumber;
+ // Whether the sequence is completed. (only consider capture result)
+ private boolean mSequenceCompleted;
+ // Whether the inflight request is completed. (consider result, buffers, and notifies)
+ private boolean mInflightCompleted;
/**
* Create a request-last-frame-numbers holder with a list of requests, request ID, and
@@ -89,6 +93,8 @@ public class RequestLastFrameNumbersHolder {
mLastReprocessFrameNumber = lastReprocessFrameNumber;
mLastZslStillFrameNumber = lastZslStillFrameNumber;
mRequestId = requestInfo.getRequestId();
+ mSequenceCompleted = false;
+ mInflightCompleted = false;
}
/**
@@ -137,6 +143,8 @@ public class RequestLastFrameNumbersHolder {
mLastZslStillFrameNumber = lastZslStillFrameNumber;
mLastReprocessFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
mRequestId = requestId;
+ mSequenceCompleted = false;
+ mInflightCompleted = false;
}
/**
@@ -177,5 +185,34 @@ public class RequestLastFrameNumbersHolder {
public int getRequestId() {
return mRequestId;
}
+
+ /**
+ * Return whether the capture sequence is completed.
+ */
+ public boolean isSequenceCompleted() {
+ return mSequenceCompleted;
+ }
+
+ /**
+ * Mark the capture sequence as completed.
+ */
+ public void markSequenceCompleted() {
+ mSequenceCompleted = true;
+ }
+
+ /**
+ * Return whether the inflight capture is completed.
+ */
+ public boolean isInflightCompleted() {
+ return mInflightCompleted;
+ }
+
+ /**
+ * Mark the inflight capture as completed.
+ */
+ public void markInflightCompleted() {
+ mInflightCompleted = true;
+ }
+
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index fbc9ac3229c3..fdd578c419d8 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -109,11 +109,12 @@ public class LegacyCameraDevice implements AutoCloseable {
}
if (holder == null) {
return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
- ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, null);
+ ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, null,
+ ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
}
return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
/*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
- /*partialResultCount*/1, errorStreamId, null);
+ /*partialResultCount*/1, errorStreamId, null, holder.getFrameNumber(), -1, -1);
}
/**
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 5ab035496a43..1ef4f1741e3a 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -18,12 +18,13 @@ package android.net;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
-import android.net.shared.InetAddressUtils;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
+import com.android.net.module.util.InetAddressUtils;
+
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
diff --git a/core/java/android/net/DnsPacket.java b/core/java/android/net/DnsPacket.java
deleted file mode 100644
index 83e57e0a047b..000000000000
--- a/core/java/android/net/DnsPacket.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.text.TextUtils;
-
-import com.android.internal.util.BitUtils;
-
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.text.DecimalFormat;
-import java.text.FieldPosition;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Defines basic data for DNS protocol based on RFC 1035.
- * Subclasses create the specific format used in DNS packet.
- *
- * @hide
- */
-public abstract class DnsPacket {
- public class DnsHeader {
- private static final String TAG = "DnsHeader";
- public final int id;
- public final int flags;
- public final int rcode;
- private final int[] mRecordCount;
-
- /**
- * Create a new DnsHeader from a positioned ByteBuffer.
- *
- * The ByteBuffer must be in network byte order (which is the default).
- * Reads the passed ByteBuffer from its current position and decodes a DNS header.
- * When this constructor returns, the reading position of the ByteBuffer has been
- * advanced to the end of the DNS header record.
- * This is meant to chain with other methods reading a DNS response in sequence.
- */
- DnsHeader(@NonNull ByteBuffer buf) throws BufferUnderflowException {
- id = BitUtils.uint16(buf.getShort());
- flags = BitUtils.uint16(buf.getShort());
- rcode = flags & 0xF;
- mRecordCount = new int[NUM_SECTIONS];
- for (int i = 0; i < NUM_SECTIONS; ++i) {
- mRecordCount[i] = BitUtils.uint16(buf.getShort());
- }
- }
-
- /**
- * Get record count by type.
- */
- public int getRecordCount(int type) {
- return mRecordCount[type];
- }
- }
-
- /**
- * Superclass for DNS questions and DNS resource records.
- *
- * DNS questions (No TTL/RDATA)
- * DNS resource records (With TTL/RDATA)
- */
- public class DnsRecord {
- private static final int MAXNAMESIZE = 255;
- private static final int MAXLABELSIZE = 63;
- private static final int MAXLABELCOUNT = 128;
- private static final int NAME_NORMAL = 0;
- private static final int NAME_COMPRESSION = 0xC0;
- private final DecimalFormat byteFormat = new DecimalFormat();
- private final FieldPosition pos = new FieldPosition(0);
-
- private static final String TAG = "DnsRecord";
-
- public final String dName;
- public final int nsType;
- public final int nsClass;
- public final long ttl;
- private final byte[] mRdata;
-
- /**
- * Create a new DnsRecord from a positioned ByteBuffer.
- *
- * Reads the passed ByteBuffer from its current position and decodes a DNS record.
- * When this constructor returns, the reading position of the ByteBuffer has been
- * advanced to the end of the DNS header record.
- * This is meant to chain with other methods reading a DNS response in sequence.
- *
- * @param ByteBuffer input of record, must be in network byte order
- * (which is the default).
- */
- DnsRecord(int recordType, @NonNull ByteBuffer buf)
- throws BufferUnderflowException, ParseException {
- dName = parseName(buf, 0 /* Parse depth */);
- if (dName.length() > MAXNAMESIZE) {
- throw new ParseException(
- "Parse name fail, name size is too long: " + dName.length());
- }
- nsType = BitUtils.uint16(buf.getShort());
- nsClass = BitUtils.uint16(buf.getShort());
-
- if (recordType != QDSECTION) {
- ttl = BitUtils.uint32(buf.getInt());
- final int length = BitUtils.uint16(buf.getShort());
- mRdata = new byte[length];
- buf.get(mRdata);
- } else {
- ttl = 0;
- mRdata = null;
- }
- }
-
- /**
- * Get a copy of rdata.
- */
- @Nullable
- public byte[] getRR() {
- return (mRdata == null) ? null : mRdata.clone();
- }
-
- /**
- * Convert label from {@code byte[]} to {@code String}
- *
- * Follows the same conversion rules of the native code (ns_name.c in libc)
- */
- private String labelToString(@NonNull byte[] label) {
- final StringBuffer sb = new StringBuffer();
- for (int i = 0; i < label.length; ++i) {
- int b = BitUtils.uint8(label[i]);
- // Control characters and non-ASCII characters.
- if (b <= 0x20 || b >= 0x7f) {
- // Append the byte as an escaped decimal number, e.g., "\19" for 0x13.
- sb.append('\\');
- byteFormat.format(b, sb, pos);
- } else if (b == '"' || b == '.' || b == ';' || b == '\\'
- || b == '(' || b == ')' || b == '@' || b == '$') {
- // Append the byte as an escaped character, e.g., "\:" for 0x3a.
- sb.append('\\');
- sb.append((char) b);
- } else {
- // Append the byte as a character, e.g., "a" for 0x61.
- sb.append((char) b);
- }
- }
- return sb.toString();
- }
-
- private String parseName(@NonNull ByteBuffer buf, int depth) throws
- BufferUnderflowException, ParseException {
- if (depth > MAXLABELCOUNT) {
- throw new ParseException("Failed to parse name, too many labels");
- }
- final int len = BitUtils.uint8(buf.get());
- final int mask = len & NAME_COMPRESSION;
- if (0 == len) {
- return "";
- } else if (mask != NAME_NORMAL && mask != NAME_COMPRESSION) {
- throw new ParseException("Parse name fail, bad label type");
- } else if (mask == NAME_COMPRESSION) {
- // Name compression based on RFC 1035 - 4.1.4 Message compression
- final int offset = ((len & ~NAME_COMPRESSION) << 8) + BitUtils.uint8(buf.get());
- final int oldPos = buf.position();
- if (offset >= oldPos - 2) {
- throw new ParseException("Parse compression name fail, invalid compression");
- }
- buf.position(offset);
- final String pointed = parseName(buf, depth + 1);
- buf.position(oldPos);
- return pointed;
- } else {
- final byte[] label = new byte[len];
- buf.get(label);
- final String head = labelToString(label);
- if (head.length() > MAXLABELSIZE) {
- throw new ParseException("Parse name fail, invalid label length");
- }
- final String tail = parseName(buf, depth + 1);
- return TextUtils.isEmpty(tail) ? head : head + "." + tail;
- }
- }
- }
-
- public static final int QDSECTION = 0;
- public static final int ANSECTION = 1;
- public static final int NSSECTION = 2;
- public static final int ARSECTION = 3;
- private static final int NUM_SECTIONS = ARSECTION + 1;
-
- private static final String TAG = DnsPacket.class.getSimpleName();
-
- protected final DnsHeader mHeader;
- protected final List<DnsRecord>[] mRecords;
-
- protected DnsPacket(@NonNull byte[] data) throws ParseException {
- if (null == data) throw new ParseException("Parse header failed, null input data");
- final ByteBuffer buffer;
- try {
- buffer = ByteBuffer.wrap(data);
- mHeader = new DnsHeader(buffer);
- } catch (BufferUnderflowException e) {
- throw new ParseException("Parse Header fail, bad input data", e);
- }
-
- mRecords = new ArrayList[NUM_SECTIONS];
-
- for (int i = 0; i < NUM_SECTIONS; ++i) {
- final int count = mHeader.getRecordCount(i);
- if (count > 0) {
- mRecords[i] = new ArrayList(count);
- }
- for (int j = 0; j < count; ++j) {
- try {
- mRecords[i].add(new DnsRecord(i, buffer));
- } catch (BufferUnderflowException e) {
- throw new ParseException("Parse record fail", e);
- }
- }
- }
- }
-}
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index 0b1a84534e38..3f7660f5709a 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -38,6 +38,8 @@ import android.os.MessageQueue;
import android.system.ErrnoException;
import android.util.Log;
+import com.android.net.module.util.DnsPacket;
+
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -97,7 +99,7 @@ public final class DnsResolver {
@interface DnsError {}
/**
* Indicates that there was an error parsing the response the query.
- * The cause of this error is available via getCause() and is a ParseException.
+ * The cause of this error is available via getCause() and is a {@link ParseException}.
*/
public static final int ERROR_PARSE = 0;
/**
@@ -290,8 +292,15 @@ public final class DnsResolver {
}
try {
mAllAnswers.addAll(new DnsAddressAnswer(answer).getAddresses());
- } catch (ParseException e) {
- mDnsException = new DnsException(ERROR_PARSE, e);
+ } catch (DnsPacket.ParseException e) {
+ // Convert the com.android.net.module.util.DnsPacket.ParseException to an
+ // android.net.ParseException. This is the type that was used in Q and is implied
+ // by the public documentation of ERROR_PARSE.
+ //
+ // DnsPacket cannot throw android.net.ParseException directly because it's @hide.
+ ParseException pe = new ParseException(e.reason, e.getCause());
+ pe.setStackTrace(e.getStackTrace());
+ mDnsException = new DnsException(ERROR_PARSE, pe);
}
maybeReportAnswer();
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 779f7bc91e8f..97a7ecc3fb15 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -21,13 +21,14 @@ import static android.system.OsConstants.AF_INET6;
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
-import android.net.shared.Inet4AddressUtils;
import android.os.Build;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
import android.util.Pair;
+import com.android.net.module.util.Inet4AddressUtils;
+
import java.io.FileDescriptor;
import java.math.BigInteger;
import java.net.Inet4Address;
@@ -155,6 +156,14 @@ public class NetworkUtils {
public static native Network getDnsNetwork() throws ErrnoException;
/**
+ * Allow/Disallow creating AF_INET/AF_INET6 sockets and DNS lookups for current process.
+ *
+ * @param allowNetworking whether to allow or disallow creating AF_INET/AF_INET6 sockets
+ * and DNS lookups.
+ */
+ public static native void setAllowNetworkingForProcess(boolean allowNetworking);
+
+ /**
* Get the tcp repair window associated with the {@code fd}.
*
* @param fd the tcp socket's {@link FileDescriptor}.
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index f24a9bd53039..a973455baa04 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -21,11 +21,11 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
-import android.net.shared.InetAddressUtils;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.Preconditions;
+import com.android.net.module.util.InetAddressUtils;
import java.net.InetAddress;
import java.util.ArrayList;
diff --git a/core/java/android/net/shared/Inet4AddressUtils.java b/core/java/android/net/shared/Inet4AddressUtils.java
deleted file mode 100644
index bec0c84fa689..000000000000
--- a/core/java/android/net/shared/Inet4AddressUtils.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.shared;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * Collection of utilities to work with IPv4 addresses.
- * @hide
- */
-public class Inet4AddressUtils {
-
- /**
- * Convert a IPv4 address from an integer to an InetAddress (0x04030201 -> 1.2.3.4)
- *
- * <p>This method uses the higher-order int bytes as the lower-order IPv4 address bytes,
- * which is an unusual convention. Consider {@link #intToInet4AddressHTH(int)} instead.
- * @param hostAddress an int coding for an IPv4 address, where higher-order int byte is
- * lower-order IPv4 address byte
- */
- public static Inet4Address intToInet4AddressHTL(int hostAddress) {
- return intToInet4AddressHTH(Integer.reverseBytes(hostAddress));
- }
-
- /**
- * Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4)
- * @param hostAddress an int coding for an IPv4 address
- */
- public static Inet4Address intToInet4AddressHTH(int hostAddress) {
- byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)),
- (byte) (0xff & (hostAddress >> 16)),
- (byte) (0xff & (hostAddress >> 8)),
- (byte) (0xff & hostAddress) };
-
- try {
- return (Inet4Address) InetAddress.getByAddress(addressBytes);
- } catch (UnknownHostException e) {
- throw new AssertionError();
- }
- }
-
- /**
- * Convert an IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x01020304)
- *
- * <p>This conversion can help order IP addresses: considering the ordering
- * 192.0.2.1 < 192.0.2.2 < ..., resulting ints will follow that ordering if read as unsigned
- * integers with {@link Integer#toUnsignedLong}.
- * @param inetAddr is an InetAddress corresponding to the IPv4 address
- * @return the IP address as integer
- */
- public static int inet4AddressToIntHTH(Inet4Address inetAddr)
- throws IllegalArgumentException {
- byte [] addr = inetAddr.getAddress();
- return ((addr[0] & 0xff) << 24) | ((addr[1] & 0xff) << 16)
- | ((addr[2] & 0xff) << 8) | (addr[3] & 0xff);
- }
-
- /**
- * Convert a IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x04030201)
- *
- * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes,
- * which is an unusual convention. Consider {@link #inet4AddressToIntHTH(Inet4Address)} instead.
- * @param inetAddr is an InetAddress corresponding to the IPv4 address
- * @return the IP address as integer
- */
- public static int inet4AddressToIntHTL(Inet4Address inetAddr) {
- return Integer.reverseBytes(inet4AddressToIntHTH(inetAddr));
- }
-
- /**
- * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0xffff8000)
- * @return the IPv4 netmask as an integer
- */
- public static int prefixLengthToV4NetmaskIntHTH(int prefixLength)
- throws IllegalArgumentException {
- if (prefixLength < 0 || prefixLength > 32) {
- throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)");
- }
- // (int)a << b is equivalent to a << (b & 0x1f): can't shift by 32 (-1 << 32 == -1)
- return prefixLength == 0 ? 0 : 0xffffffff << (32 - prefixLength);
- }
-
- /**
- * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0x0080ffff).
- *
- * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes,
- * which is an unusual convention. Consider {@link #prefixLengthToV4NetmaskIntHTH(int)} instead.
- * @return the IPv4 netmask as an integer
- */
- public static int prefixLengthToV4NetmaskIntHTL(int prefixLength)
- throws IllegalArgumentException {
- return Integer.reverseBytes(prefixLengthToV4NetmaskIntHTH(prefixLength));
- }
-
- /**
- * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous.
- * @param netmask as a {@code Inet4Address}.
- * @return the network prefix length
- * @throws IllegalArgumentException the specified netmask was not contiguous.
- * @hide
- */
- public static int netmaskToPrefixLength(Inet4Address netmask) {
- // inetAddressToInt returns an int in *network* byte order.
- int i = inet4AddressToIntHTH(netmask);
- int prefixLength = Integer.bitCount(i);
- int trailingZeros = Integer.numberOfTrailingZeros(i);
- if (trailingZeros != 32 - prefixLength) {
- throw new IllegalArgumentException("Non-contiguous netmask: " + Integer.toHexString(i));
- }
- return prefixLength;
- }
-
- /**
- * Returns the implicit netmask of an IPv4 address, as was the custom before 1993.
- */
- public static int getImplicitNetmask(Inet4Address address) {
- int firstByte = address.getAddress()[0] & 0xff; // Convert to an unsigned value.
- if (firstByte < 128) {
- return 8;
- } else if (firstByte < 192) {
- return 16;
- } else if (firstByte < 224) {
- return 24;
- } else {
- return 32; // Will likely not end well for other reasons.
- }
- }
-
- /**
- * Get the broadcast address for a given prefix.
- *
- * <p>For example 192.168.0.1/24 -> 192.168.0.255
- */
- public static Inet4Address getBroadcastAddress(Inet4Address addr, int prefixLength)
- throws IllegalArgumentException {
- final int intBroadcastAddr = inet4AddressToIntHTH(addr)
- | ~prefixLengthToV4NetmaskIntHTH(prefixLength);
- return intToInet4AddressHTH(intBroadcastAddr);
- }
-
- /**
- * Get a prefix mask as Inet4Address for a given prefix length.
- *
- * <p>For example 20 -> 255.255.240.0
- */
- public static Inet4Address getPrefixMaskAsInet4Address(int prefixLength)
- throws IllegalArgumentException {
- return intToInet4AddressHTH(prefixLengthToV4NetmaskIntHTH(prefixLength));
- }
-}
diff --git a/core/java/android/net/shared/InetAddressUtils.java b/core/java/android/net/shared/InetAddressUtils.java
deleted file mode 100644
index c9ee3a7cce4b..000000000000
--- a/core/java/android/net/shared/InetAddressUtils.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.shared;
-
-import android.os.Parcel;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * Collection of utilities to interact with {@link InetAddress}
- * @hide
- */
-public class InetAddressUtils {
-
- /**
- * Writes an InetAddress to a parcel. The address may be null. This is likely faster than
- * calling writeSerializable.
- * @hide
- */
- public static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) {
- byte[] addressArray = (address != null) ? address.getAddress() : null;
- parcel.writeByteArray(addressArray);
- }
-
- /**
- * Reads an InetAddress from a parcel. Returns null if the address that was written was null
- * or if the data is invalid.
- * @hide
- */
- public static InetAddress unparcelInetAddress(Parcel in) {
- byte[] addressArray = in.createByteArray();
- if (addressArray == null) {
- return null;
- }
- try {
- return InetAddress.getByAddress(addressArray);
- } catch (UnknownHostException e) {
- return null;
- }
- }
-
- private InetAddressUtils() {}
-}
diff --git a/core/java/android/os/CarrierAssociatedAppEntry.aidl b/core/java/android/os/CarrierAssociatedAppEntry.aidl
new file mode 100644
index 000000000000..a9b1055ee174
--- /dev/null
+++ b/core/java/android/os/CarrierAssociatedAppEntry.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+parcelable CarrierAssociatedAppEntry;
diff --git a/core/java/android/os/CarrierAssociatedAppEntry.java b/core/java/android/os/CarrierAssociatedAppEntry.java
new file mode 100644
index 000000000000..13f6eb63e29c
--- /dev/null
+++ b/core/java/android/os/CarrierAssociatedAppEntry.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+/**
+ * Represents a carrier app entry for use with {@link SystemConfigService}.
+ *
+ * @hide
+ */
+public final class CarrierAssociatedAppEntry implements Parcelable {
+
+ /**
+ * For carrier-associated app entries that don't specify the addedInSdk XML
+ * attribute.
+ */
+ public static final int SDK_UNSPECIFIED = -1;
+
+ public final String packageName;
+ /** May be {@link #SDK_UNSPECIFIED}. */
+ public final int addedInSdk;
+
+ public CarrierAssociatedAppEntry(String packageName, int addedInSdk) {
+ this.packageName = packageName;
+ this.addedInSdk = addedInSdk;
+ }
+
+ public CarrierAssociatedAppEntry(Parcel in) {
+ packageName = in.readString();
+ addedInSdk = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(packageName);
+ dest.writeInt(addedInSdk);
+ }
+
+ public static final Parcelable.Creator<CarrierAssociatedAppEntry> CREATOR =
+ new Parcelable.Creator<CarrierAssociatedAppEntry>() {
+ @Override
+ public CarrierAssociatedAppEntry createFromParcel(Parcel source) {
+ return new CarrierAssociatedAppEntry(source);
+ }
+
+ @Override
+ public CarrierAssociatedAppEntry[] newArray(int size) {
+ return new CarrierAssociatedAppEntry[size];
+ }
+ };
+}
diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl
index d3b029854112..52f0ce1f054f 100644
--- a/core/java/android/os/ISystemConfig.aidl
+++ b/core/java/android/os/ISystemConfig.aidl
@@ -30,4 +30,9 @@ interface ISystemConfig {
* @see SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedApps
*/
Map getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
+
+ /**
+ * @see SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries
+ */
+ Map getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries();
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5d2c9d18c00c..a4077fbee892 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -228,6 +228,13 @@ public class Process {
*/
public static final int EXT_OBB_RW_GID = 1079;
+ /**
+ * GID that corresponds to the INTERNET permission.
+ * Must match the value of AID_INET.
+ * @hide
+ */
+ public static final int INET_GID = 3003;
+
/** {@hide} */
public static final int NOBODY_UID = 9999;
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index 3a9ce2fa85f1..12a1ffaf69c1 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -88,4 +88,29 @@ public class SystemConfigManager {
return Collections.emptyMap();
}
}
+
+ /**
+ * Returns a map that describes helper apps associated with carrier apps that, like the apps
+ * returned by {@link #getDisabledUntilUsedPreinstalledCarrierApps()}, should be disabled until
+ * the correct SIM is inserted into the device.
+ *
+ * <p>TODO(b/159069037) expose this and get rid of the other method that omits SDK version.
+ *
+ * @return A map with keys corresponding to package names returned by
+ * {@link #getDisabledUntilUsedPreinstalledCarrierApps()} and values as lists of package
+ * names of helper apps and the SDK versions when they were first added.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.READ_CARRIER_APP_INFO)
+ public @NonNull Map<String, List<CarrierAssociatedAppEntry>>
+ getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries() {
+ try {
+ return (Map<String, List<CarrierAssociatedAppEntry>>)
+ mInterface.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Caught remote exception", e);
+ return Collections.emptyMap();
+ }
+ }
}
diff --git a/core/java/android/os/Users.md b/core/java/android/os/Users.md
index 3bbbe5452fd3..b019b0dc178b 100644
--- a/core/java/android/os/Users.md
+++ b/core/java/android/os/Users.md
@@ -18,54 +18,80 @@
## Concepts
-### User
+### Users and profiles
-A user of a device e.g. usually a human being. Each user has its own home screen.
+#### User
-#### User Profile
+A user is a representation of a person using a device, with their own distinct application data
+and some unique settings. Throughout this document, the word 'user' will be used in this technical
+sense, i.e. for this virtual environment, whereas the word 'person' will be used to denote an actual
+human interacting with the device.
-A user can have multiple profiles. E.g. one for the private life and one for work. Each profile
-has a different set of apps and accounts but they share one home screen. All profiles of a
-profile group can be active at the same time.
-
-Each profile has a separate [`userId`](#int-userid). Unless needed user profiles are treated as
-completely separate users.
+Each user has a separate [`userId`](#int-userid).
#### Profile Group
-All user profiles that share a home screen. You can list the profiles of a user via
-`UserManager#getEnabledProfiles` (you usually don't deal with disabled profiles)
+Often, there is a 1-to-1 mapping of people who use a device to 'users'; e.g. there may be two users
+on a device - the owner and a guest, each with their own separate home screen.
-#### Foreground user vs background user
+However, Android also supports multiple profiles for a single person, e.g. one for their private
+life and one for work, both sharing a single home screen.
+Each profile in a profile group is a distinct user, with a unique [`userId`](#int-userid), and have
+a different set of apps and accounts,
+but they share a single UI, single launcher, and single wallpaper.
+All profiles of a profile group can be active at the same time.
-Only a single user profile group can be in the foreground. This is the user profile the user
-currently interacts with.
+You can list the profiles of a user via `UserManager#getEnabledProfiles` (you usually don't deal
+with disabled profiles)
-#### Parent user (profile)
+#### Parent user
-The main profile of a profile group, usually the personal (as opposed to work) profile. Get this via
-`UserManager#getProfileParent` (returns `null` if the user does not have profiles)
+The main user of a profile group, to which the other profiles of the group 'belong'.
+This is usually the personal (as opposed to work) profile. Get this via
+`UserManager#getProfileParent` (returns `null` if the user does not have profiles).
-#### Managed user (profile)
+#### Profile (Managed profile)
-The other profiles of a profile group. The name comes from the fact that these profiles are usually
+A profile of the parent user, i.e. a profile belonging to the same profile group as a parent user,
+with whom they share a single home screen.
+Currently, the only type of profile supported in AOSP is a 'Managed Profile'.
+The name comes from the fact that these profiles are usually
managed by a device policy controller app. You can create a managed profile from within the device
policy controller app on your phone.
+Note that, as a member of the profile group, the parent user may sometimes also be considered a
+'profile', but generally speaking, the word 'profile' denotes a user that is subordinate to a
+parent.
+
+#### Foreground user vs background user
+
+Only a single user can be in the foreground.
+This is the user with whom the person using the device is currently interacting, or, in the case
+of profiles, the parent profile of this user.
+All other running users are background users.
+Some users may not be running at all, neither in the foreground nor the background.
+
#### Account
-An account of a user profile with a (usually internet based) service. E.g. aname@gmail.com or
-aname@yahoo.com. Each profile can have multiple accounts. A profile does not have to have a
+An account of a user with a (usually internet based) service. E.g. aname@gmail.com or
+aname@yahoo.com. Each user can have multiple accounts. A user does not have to have a
account.
+#### System User
+
+The user with [`userId`](#int-userid) 0 denotes the system user, which is always required to be
+running.
+
+On most devices, the system user is also used by the primary person using the device; however,
+on certain types of devices, the system user may be a stand-alone user, not intended for direct
+human interaction.
+
## Data types
### int userId
-... usually marked as `@UserIdInt`
-
-The id of a user profile. List all users via `adb shell dumpsys user`. There is no data type for a
-user, all you can do is using the user id of the parent profile as a proxy for the user.
+The id of a user. List all users via `adb shell dumpsys user`.
+In code, these are sometimes marked as `@UserIdInt`.
### int uid
@@ -97,10 +123,10 @@ mechanism should be access controlled by permissions.
A system service should deal with users being started and stopped by overriding
`SystemService.onSwitchUser` and `SystemService.onStopUser`.
-If users profiles become inactive the system should stop all apps of this profile from interacting
+If a user become inactive the system should stop all apps of this user from interacting
with other apps or the system.
-Another important lifecycle event is `onUnlockUser`. Only for unlocked user profiles you can access
+Another important lifecycle event is `onUnlockUser`. Only for an unlocked user can you access
all data, e.g. which packages are installed.
You only want to deal with user profiles that
diff --git a/core/java/android/permission/Permissions.md b/core/java/android/permission/Permissions.md
index 2bf08e2ff2d4..1ef3ad211cee 100644
--- a/core/java/android/permission/Permissions.md
+++ b/core/java/android/permission/Permissions.md
@@ -706,9 +706,9 @@ App-op permissions are user-switchable permissions that are not runtime permissi
be used for permissions that are really only meant to be ever granted to a very small amount of
apps. Traditionally granting these permissions is intentionally very heavy weight so that the
user really needs to understand the use case. For example one use case is the
-`INTERACT_ACROSS_PROFILES` permission that allows apps of different
-[user profiles](../os/Users.md#user-profile) to interact. Of course this is breaking a very basic
-security container and hence should only every be granted with a lot of care.
+`INTERACT_ACROSS_PROFILES` permission that allows apps of different users within the same
+[profile group](../os/Users.md#profile-group) to interact. Of course this is breaking a very basic
+security container and hence should only ever be granted with a lot of care.
**Warning:** Most app-op permissions follow this logic, but most of them also have exceptions
and special behavior. Hence this section is a guideline, not a rule.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cd2467f9157d..1fafbd3bbed1 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8521,14 +8521,15 @@ public final class Settings {
public static final int VR_DISPLAY_MODE_OFF = 1;
/**
- * Whether CarrierAppUtils#disableCarrierAppsUntilPrivileged has been executed at least
- * once.
+ * The latest SDK version that CarrierAppUtils#disableCarrierAppsUntilPrivileged has been
+ * executed for.
*
* <p>This is used to ensure that we only take one pass which will disable apps that are not
* privileged (if any). From then on, we only want to enable apps (when a matching SIM is
* inserted), to avoid disabling an app that the user might actively be using.
*
- * <p>Will be set to 1 once executed.
+ * <p>Will be set to {@link android.os.Build.VERSION#SDK_INT} once executed. Note that older
+ * SDK versions prior to R set 1 for this value.
*
* @hide
*/
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 3ea443bab3f8..8790fb2299f5 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -64,7 +64,7 @@ public abstract class InlineSuggestionRenderService extends Service {
public static final String SERVICE_INTERFACE =
"android.service.autofill.InlineSuggestionRenderService";
- private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper(), null, true);
private IInlineSuggestionUiCallback mCallback;
@@ -192,15 +192,22 @@ public abstract class InlineSuggestionRenderService extends Service {
}
return true;
});
-
- try {
- InlineSuggestionUiImpl uiImpl = new InlineSuggestionUiImpl(host, mHandler);
- mActiveInlineSuggestions.put(uiImpl, true);
- callback.onContent(new InlineSuggestionUiWrapper(uiImpl), host.getSurfacePackage(),
- measuredSize.getWidth(), measuredSize.getHeight());
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException calling onContent()");
- }
+ final InlineSuggestionUiImpl uiImpl = new InlineSuggestionUiImpl(host, mMainHandler);
+ mActiveInlineSuggestions.put(uiImpl, true);
+
+ // We post the callback invocation to the end of the main thread handler queue, to make
+ // sure the callback happens after the views are drawn. This is needed because calling
+ // {@link SurfaceControlViewHost#setView()} will post a task to the main thread
+ // to draw the view asynchronously.
+ mMainHandler.post(() -> {
+ try {
+ callback.onContent(new InlineSuggestionUiWrapper(uiImpl),
+ host.getSurfacePackage(),
+ measuredSize.getWidth(), measuredSize.getHeight());
+ } catch (RemoteException e) {
+ Log.w(TAG, "RemoteException calling onContent()");
+ }
+ });
} finally {
updateDisplay(Display.DEFAULT_DISPLAY);
}
@@ -305,7 +312,7 @@ public abstract class InlineSuggestionRenderService extends Service {
public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
@NonNull InlinePresentation presentation, int width, int height,
@Nullable IBinder hostInputToken, int displayId) {
- mHandler.sendMessage(
+ mMainHandler.sendMessage(
obtainMessage(InlineSuggestionRenderService::handleRenderSuggestion,
InlineSuggestionRenderService.this, callback, presentation,
width, height, hostInputToken, displayId));
@@ -313,7 +320,7 @@ public abstract class InlineSuggestionRenderService extends Service {
@Override
public void getInlineSuggestionsRendererInfo(@NonNull RemoteCallback callback) {
- mHandler.sendMessage(obtainMessage(
+ mMainHandler.sendMessage(obtainMessage(
InlineSuggestionRenderService::handleGetInlineSuggestionsRendererInfo,
InlineSuggestionRenderService.this, callback));
}
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index c2234bad3803..95cc64ae8aab 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -564,9 +564,9 @@ public abstract class AugmentedAutofillService extends Service {
}
void reportResult(@Nullable List<Dataset> inlineSuggestionsData,
- @Nullable Bundle clientState) {
+ @Nullable Bundle clientState, boolean showingFillWindow) {
try {
- mCallback.onSuccess(inlineSuggestionsData, clientState);
+ mCallback.onSuccess(inlineSuggestionsData, clientState, showingFillWindow);
} catch (RemoteException e) {
Log.e(TAG, "Error calling back with the inline suggestions data: " + e);
}
diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
index 8ba5c173890c..fc3baf1c9836 100644
--- a/core/java/android/service/autofill/augmented/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -56,23 +56,24 @@ public final class FillCallback {
if (response == null) {
mProxy.logEvent(AutofillProxy.REPORT_EVENT_NO_RESPONSE);
- mProxy.reportResult(/* inlineSuggestionsData */ null, /* clientState */ null);
+ mProxy.reportResult(/* inlineSuggestionsData */ null, /* clientState */
+ null, /* showingFillWindow */ false);
return;
}
- List<Dataset> inlineSuggestions = response.getInlineSuggestions();
- Bundle clientState = response.getClientState();
- // We need to report result regardless of whether inline suggestions are returned or not.
- mProxy.reportResult(inlineSuggestions, clientState);
+ final List<Dataset> inlineSuggestions = response.getInlineSuggestions();
+ final Bundle clientState = response.getClientState();
+ final FillWindow fillWindow = response.getFillWindow();
+ boolean showingFillWindow = false;
if (inlineSuggestions != null && !inlineSuggestions.isEmpty()) {
mProxy.logEvent(AutofillProxy.REPORT_EVENT_INLINE_RESPONSE);
- return;
- }
-
- final FillWindow fillWindow = response.getFillWindow();
- if (fillWindow != null) {
+ } else if (fillWindow != null) {
fillWindow.show();
+ showingFillWindow = true;
}
+ // We need to report result regardless of whether inline suggestions are returned or not.
+ mProxy.reportResult(inlineSuggestions, clientState, showingFillWindow);
+
// TODO(b/123099468): must notify the server so it can update the session state to avoid
// showing conflicting UIs (for example, if a new request is made to the main autofill
// service and it now wants to show something).
diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 077df6cf16ef..8e866466e8df 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -208,12 +208,18 @@ public final class FillWindow implements AutoCloseable {
if (sDebug) Log.d(TAG, "handleShow()");
synchronized (mLock) {
if (mWm != null && mFillView != null) {
- p.flags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
- if (!mShowing) {
- mWm.addView(mFillView, p);
- mShowing = true;
- } else {
- mWm.updateViewLayout(mFillView, p);
+ try {
+ p.flags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+ if (!mShowing) {
+ mWm.addView(mFillView, p);
+ mShowing = true;
+ } else {
+ mWm.updateViewLayout(mFillView, p);
+ }
+ } catch (WindowManager.BadTokenException e) {
+ if (sDebug) Log.d(TAG, "Filed with token " + p.token + " gone.");
+ } catch (IllegalStateException e) {
+ if (sDebug) Log.d(TAG, "Exception showing window.");
}
}
}
@@ -223,8 +229,12 @@ public final class FillWindow implements AutoCloseable {
if (sDebug) Log.d(TAG, "handleHide()");
synchronized (mLock) {
if (mWm != null && mFillView != null && mShowing) {
- mWm.removeView(mFillView);
- mShowing = false;
+ try {
+ mWm.removeView(mFillView);
+ mShowing = false;
+ } catch (IllegalStateException e) {
+ if (sDebug) Log.d(TAG, "Exception hiding window.");
+ }
}
}
}
diff --git a/core/java/android/service/autofill/augmented/IFillCallback.aidl b/core/java/android/service/autofill/augmented/IFillCallback.aidl
index 609e382e2b96..4dfdd4db27e5 100644
--- a/core/java/android/service/autofill/augmented/IFillCallback.aidl
+++ b/core/java/android/service/autofill/augmented/IFillCallback.aidl
@@ -30,7 +30,9 @@ import java.util.List;
*/
interface IFillCallback {
void onCancellable(in ICancellationSignal cancellation);
- void onSuccess(in @nullable List<Dataset> inlineSuggestionsData, in @nullable Bundle clientState);
+ void onSuccess(in @nullable List<Dataset> inlineSuggestionsData,
+ in @nullable Bundle clientState,
+ boolean showingFillWindow);
boolean isCompleted();
void cancel();
}
diff --git a/core/java/android/service/controls/Control.java b/core/java/android/service/controls/Control.java
index 8383072a48e3..2868f1bf3547 100644
--- a/core/java/android/service/controls/Control.java
+++ b/core/java/android/service/controls/Control.java
@@ -789,6 +789,13 @@ public final class Control implements Parcelable {
}
/**
+ * Set the {@link ControlTemplate} to define the primary user interaction
+ *
+ * Devices may support a variety of user interactions, and all interactions cannot be
+ * represented with a single {@link ControlTemplate}. Therefore, the selected template
+ * should be most closely aligned with what the expected primary device action will be.
+ * Any secondary interactions can be done via the {@link #setAppIntent(PendingIntent)}.
+ *
* @param controlTemplate instance of {@link ControlTemplate}, that defines how the
* {@link Control} will behave and what interactions are
* available to the user
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f944dd78dc3d..0d420c5936ae 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1184,7 +1184,8 @@ public abstract class WallpaperService extends Service {
// may have been destroyed so now we need to make
// sure it is re-created.
doOffsetsChanged(false);
- updateSurface(false, false, false);
+ // force relayout to get new surface
+ updateSurface(true, false, false);
}
onVisibilityChanged(visible);
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 8acf5fa8bdfe..537498c44d5e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -67,7 +67,6 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "true");
DEFAULT_FLAGS.put("settings_tether_all_in_one", "false");
- DEFAULT_FLAGS.put("settings_contextual_home2", "true");
}
/**
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 2a4b65d23e64..6efe95cb9e92 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -420,6 +420,7 @@ final class ApkSigningBlockUtils {
static final int CONTENT_DIGEST_CHUNKED_SHA256 = 1;
static final int CONTENT_DIGEST_CHUNKED_SHA512 = 2;
static final int CONTENT_DIGEST_VERITY_CHUNKED_SHA256 = 3;
+ static final int CONTENT_DIGEST_SHA256 = 4;
private static final int[] V4_CONTENT_DIGEST_ALGORITHMS =
{CONTENT_DIGEST_CHUNKED_SHA512, CONTENT_DIGEST_VERITY_CHUNKED_SHA256,
diff --git a/core/java/android/util/apk/SourceStampVerifier.java b/core/java/android/util/apk/SourceStampVerifier.java
index a7ae32d1baa2..5fc242353d51 100644
--- a/core/java/android/util/apk/SourceStampVerifier.java
+++ b/core/java/android/util/apk/SourceStampVerifier.java
@@ -16,6 +16,7 @@
package android.util.apk;
+import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_SHA256;
import static android.util.apk.ApkSigningBlockUtils.compareSignatureAlgorithm;
import static android.util.apk.ApkSigningBlockUtils.getLengthPrefixedSlice;
import static android.util.apk.ApkSigningBlockUtils.getSignatureAlgorithmContentDigestAlgorithm;
@@ -27,12 +28,10 @@ import android.util.Pair;
import android.util.Slog;
import android.util.jar.StrictJarFile;
-import libcore.io.IoUtils;
+import libcore.io.Streams;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
@@ -49,11 +48,13 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
+import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
@@ -74,7 +75,11 @@ public abstract class SourceStampVerifier {
private static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a;
private static final int APK_SIGNATURE_SCHEME_V3_BLOCK_ID = 0xf05368c0;
- private static final int SOURCE_STAMP_BLOCK_ID = 0x2b09189e;
+ private static final int SOURCE_STAMP_BLOCK_ID = 0x6dff800d;
+
+ private static final int VERSION_JAR_SIGNATURE_SCHEME = 1;
+ private static final int VERSION_APK_SIGNATURE_SCHEME_V2 = 2;
+ private static final int VERSION_APK_SIGNATURE_SCHEME_V3 = 3;
/** Name of the SourceStamp certificate hash ZIP entry in APKs. */
private static final String SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME = "stamp-cert-sha256";
@@ -115,7 +120,8 @@ public abstract class SourceStampVerifier {
// SourceStamp present.
return SourceStampVerificationResult.notPresent();
}
- return verify(apk, sourceStampCertificateDigest);
+ byte[] manifestBytes = getManifestBytes(apkJar);
+ return verify(apk, sourceStampCertificateDigest, manifestBytes);
} catch (IOException e) {
// Any exception in reading the APK returns a non-present SourceStamp outcome
// without affecting the outcome of any of the other signature schemes.
@@ -126,22 +132,71 @@ public abstract class SourceStampVerifier {
}
private static SourceStampVerificationResult verify(
- RandomAccessFile apk, byte[] sourceStampCertificateDigest) {
+ RandomAccessFile apk, byte[] sourceStampCertificateDigest, byte[] manifestBytes) {
try {
SignatureInfo signatureInfo =
ApkSigningBlockUtils.findSignature(apk, SOURCE_STAMP_BLOCK_ID);
- Map<Integer, byte[]> apkContentDigests = getApkContentDigests(apk);
- return verify(signatureInfo, apkContentDigests, sourceStampCertificateDigest);
- } catch (IOException | SignatureNotFoundException e) {
+ Map<Integer, Map<Integer, byte[]>> signatureSchemeApkContentDigests =
+ getSignatureSchemeApkContentDigests(apk, manifestBytes);
+ return verify(
+ signatureInfo,
+ getSignatureSchemeDigests(signatureSchemeApkContentDigests),
+ sourceStampCertificateDigest);
+ } catch (IOException | SignatureNotFoundException | RuntimeException e) {
return SourceStampVerificationResult.notVerified();
}
}
private static SourceStampVerificationResult verify(
SignatureInfo signatureInfo,
- Map<Integer, byte[]> apkContentDigests,
+ Map<Integer, byte[]> signatureSchemeDigests,
byte[] sourceStampCertificateDigest)
throws SecurityException, IOException {
+ ByteBuffer sourceStampBlock = signatureInfo.signatureBlock;
+ ByteBuffer sourceStampBlockData =
+ ApkSigningBlockUtils.getLengthPrefixedSlice(sourceStampBlock);
+
+ X509Certificate sourceStampCertificate =
+ verifySourceStampCertificate(sourceStampBlockData, sourceStampCertificateDigest);
+
+ // Parse signed signature schemes block.
+ ByteBuffer signedSignatureSchemes =
+ ApkSigningBlockUtils.getLengthPrefixedSlice(sourceStampBlockData);
+ Map<Integer, ByteBuffer> signedSignatureSchemeData = new HashMap<>();
+ while (signedSignatureSchemes.hasRemaining()) {
+ ByteBuffer signedSignatureScheme =
+ ApkSigningBlockUtils.getLengthPrefixedSlice(signedSignatureSchemes);
+ int signatureSchemeId = signedSignatureScheme.getInt();
+ signedSignatureSchemeData.put(signatureSchemeId, signedSignatureScheme);
+ }
+
+ for (Map.Entry<Integer, byte[]> signatureSchemeDigest : signatureSchemeDigests.entrySet()) {
+ if (!signedSignatureSchemeData.containsKey(signatureSchemeDigest.getKey())) {
+ throw new SecurityException(
+ String.format(
+ "No signatures found for signature scheme %d",
+ signatureSchemeDigest.getKey()));
+ }
+ verifySourceStampSignature(
+ signedSignatureSchemeData.get(signatureSchemeDigest.getKey()),
+ sourceStampCertificate,
+ signatureSchemeDigest.getValue());
+ }
+
+ return SourceStampVerificationResult.verified(sourceStampCertificate);
+ }
+
+ /**
+ * Verify the SourceStamp certificate found in the signing block is the same as the SourceStamp
+ * certificate found in the APK. It returns the verified certificate.
+ *
+ * @param sourceStampBlockData the source stamp block in the APK signing block which contains
+ * the certificate used to sign the stamp digests.
+ * @param sourceStampCertificateDigest the source stamp certificate digest found in the APK.
+ */
+ private static X509Certificate verifySourceStampCertificate(
+ ByteBuffer sourceStampBlockData, byte[] sourceStampCertificateDigest)
+ throws IOException {
CertificateFactory certFactory;
try {
certFactory = CertificateFactory.getInstance("X.509");
@@ -149,17 +204,6 @@ public abstract class SourceStampVerifier {
throw new RuntimeException("Failed to obtain X.509 CertificateFactory", e);
}
- List<Pair<Integer, byte[]>> digests =
- apkContentDigests.entrySet().stream()
- .sorted(Map.Entry.comparingByKey())
- .map(e -> Pair.create(e.getKey(), e.getValue()))
- .collect(Collectors.toList());
- byte[] digestBytes = encodeApkContentDigests(digests);
-
- ByteBuffer sourceStampBlock = signatureInfo.signatureBlock;
- ByteBuffer sourceStampBlockData =
- ApkSigningBlockUtils.getLengthPrefixedSlice(sourceStampBlock);
-
// Parse the SourceStamp certificate.
byte[] sourceStampEncodedCertificate =
ApkSigningBlockUtils.readLengthPrefixedByteArray(sourceStampBlockData);
@@ -172,24 +216,30 @@ public abstract class SourceStampVerifier {
} catch (CertificateException e) {
throw new SecurityException("Failed to decode certificate", e);
}
- sourceStampCertificate =
- new VerbatimX509Certificate(sourceStampCertificate, sourceStampEncodedCertificate);
- // Verify the SourceStamp certificate found in the signing block is the same as the
- // SourceStamp certificate found in the APK.
- try {
- MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
- messageDigest.update(sourceStampEncodedCertificate);
- byte[] sourceStampBlockCertificateDigest = messageDigest.digest();
- if (!Arrays.equals(sourceStampCertificateDigest, sourceStampBlockCertificateDigest)) {
- throw new SecurityException("Certificate mismatch between APK and signature block");
- }
- } catch (NoSuchAlgorithmException e) {
- throw new SecurityException("Failed to find SHA-256", e);
+ byte[] sourceStampBlockCertificateDigest =
+ computeSha256Digest(sourceStampEncodedCertificate);
+ if (!Arrays.equals(sourceStampCertificateDigest, sourceStampBlockCertificateDigest)) {
+ throw new SecurityException("Certificate mismatch between APK and signature block");
}
+ return new VerbatimX509Certificate(sourceStampCertificate, sourceStampEncodedCertificate);
+ }
+
+ /**
+ * Verify the SourceStamp signature found in the signing block is signed by the SourceStamp
+ * certificate found in the APK.
+ *
+ * @param signedBlockData the source stamp block in the APK signing block which contains the
+ * stamp signed digests.
+ * @param sourceStampCertificate the source stamp certificate used to sign the stamp digests.
+ * @param digest the digest to be verified being signed by the source stamp certificate.
+ */
+ private static void verifySourceStampSignature(
+ ByteBuffer signedBlockData, X509Certificate sourceStampCertificate, byte[] digest)
+ throws IOException {
// Parse the signatures block and identify supported signatures
- ByteBuffer signatures = ApkSigningBlockUtils.getLengthPrefixedSlice(sourceStampBlockData);
+ ByteBuffer signatures = ApkSigningBlockUtils.getLengthPrefixedSlice(signedBlockData);
int signatureCount = 0;
int bestSigAlgorithm = -1;
byte[] bestSigAlgorithmSignatureBytes = null;
@@ -235,7 +285,7 @@ public abstract class SourceStampVerifier {
if (jcaSignatureAlgorithmParams != null) {
sig.setParameter(jcaSignatureAlgorithmParams);
}
- sig.update(digestBytes);
+ sig.update(digest);
sigVerified = sig.verify(bestSigAlgorithmSignatureBytes);
} catch (InvalidKeyException
| InvalidAlgorithmParameterException
@@ -247,27 +297,44 @@ public abstract class SourceStampVerifier {
if (!sigVerified) {
throw new SecurityException(jcaSignatureAlgorithm + " signature did not verify");
}
-
- return SourceStampVerificationResult.verified(sourceStampCertificate);
}
- private static Map<Integer, byte[]> getApkContentDigests(RandomAccessFile apk)
- throws IOException, SignatureNotFoundException {
- // Retrieve APK content digests in V3 signing block. If a V3 signature is not found, the APK
- // content digests would be re-tried from V2 signature.
+ private static Map<Integer, Map<Integer, byte[]>> getSignatureSchemeApkContentDigests(
+ RandomAccessFile apk, byte[] manifestBytes) throws IOException {
+ Map<Integer, Map<Integer, byte[]>> signatureSchemeApkContentDigests = new HashMap<>();
+
+ // Retrieve APK content digests in V3 signing block.
try {
SignatureInfo v3SignatureInfo =
ApkSigningBlockUtils.findSignature(apk, APK_SIGNATURE_SCHEME_V3_BLOCK_ID);
- return getApkContentDigestsFromSignatureBlock(v3SignatureInfo.signatureBlock);
+ signatureSchemeApkContentDigests.put(
+ VERSION_APK_SIGNATURE_SCHEME_V3,
+ getApkContentDigestsFromSignatureBlock(v3SignatureInfo.signatureBlock));
} catch (SignatureNotFoundException e) {
// It's fine not to find a V3 signature.
}
- // Retrieve APK content digests in V2 signing block. If a V2 signature is not found, the
- // process of retrieving APK content digests stops, and the stamp is considered un-verified.
- SignatureInfo v2SignatureInfo =
- ApkSigningBlockUtils.findSignature(apk, APK_SIGNATURE_SCHEME_V2_BLOCK_ID);
- return getApkContentDigestsFromSignatureBlock(v2SignatureInfo.signatureBlock);
+ // Retrieve APK content digests in V2 signing block.
+ try {
+ SignatureInfo v2SignatureInfo =
+ ApkSigningBlockUtils.findSignature(apk, APK_SIGNATURE_SCHEME_V2_BLOCK_ID);
+ signatureSchemeApkContentDigests.put(
+ VERSION_APK_SIGNATURE_SCHEME_V2,
+ getApkContentDigestsFromSignatureBlock(v2SignatureInfo.signatureBlock));
+ } catch (SignatureNotFoundException e) {
+ // It's fine not to find a V2 signature.
+ }
+
+ // Retrieve manifest digest.
+ if (manifestBytes != null) {
+ Map<Integer, byte[]> jarSignatureSchemeApkContentDigests = new HashMap<>();
+ jarSignatureSchemeApkContentDigests.put(
+ CONTENT_DIGEST_SHA256, computeSha256Digest(manifestBytes));
+ signatureSchemeApkContentDigests.put(
+ VERSION_JAR_SIGNATURE_SCHEME, jarSignatureSchemeApkContentDigests);
+ }
+
+ return signatureSchemeApkContentDigests;
}
private static Map<Integer, byte[]> getApkContentDigestsFromSignatureBlock(
@@ -289,27 +356,45 @@ public abstract class SourceStampVerifier {
return apkContentDigests;
}
- private static byte[] getSourceStampCertificateDigest(StrictJarFile apkJar) throws IOException {
- InputStream inputStream = null;
- try {
- ZipEntry zipEntry = apkJar.findEntry(SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME);
- if (zipEntry == null) {
- // SourceStamp certificate hash file not found, which means that there is not
- // SourceStamp present.
- return null;
- }
- inputStream = apkJar.getInputStream(zipEntry);
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ private static Map<Integer, byte[]> getSignatureSchemeDigests(
+ Map<Integer, Map<Integer, byte[]>> signatureSchemeApkContentDigests) {
+ Map<Integer, byte[]> digests = new HashMap<>();
+ for (Map.Entry<Integer, Map<Integer, byte[]>> signatureSchemeApkContentDigest :
+ signatureSchemeApkContentDigests.entrySet()) {
+ List<Pair<Integer, byte[]>> apkDigests =
+ getApkDigests(signatureSchemeApkContentDigest.getValue());
+ digests.put(
+ signatureSchemeApkContentDigest.getKey(), encodeApkContentDigests(apkDigests));
+ }
+ return digests;
+ }
- // Trying to read the certificate digest, which should be less than 1024 bytes.
- byte[] buffer = new byte[1024];
- int count = inputStream.read(buffer, 0, buffer.length);
- byteArrayOutputStream.write(buffer, 0, count);
+ private static List<Pair<Integer, byte[]>> getApkDigests(
+ Map<Integer, byte[]> apkContentDigests) {
+ List<Pair<Integer, byte[]>> digests = new ArrayList<>();
+ for (Map.Entry<Integer, byte[]> apkContentDigest : apkContentDigests.entrySet()) {
+ digests.add(Pair.create(apkContentDigest.getKey(), apkContentDigest.getValue()));
+ }
+ digests.sort(Comparator.comparing(pair -> pair.first));
+ return digests;
+ }
- return byteArrayOutputStream.toByteArray();
- } finally {
- IoUtils.closeQuietly(inputStream);
+ private static byte[] getSourceStampCertificateDigest(StrictJarFile apkJar) throws IOException {
+ ZipEntry zipEntry = apkJar.findEntry(SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME);
+ if (zipEntry == null) {
+ // SourceStamp certificate hash file not found, which means that there is not
+ // SourceStamp present.
+ return null;
+ }
+ return Streams.readFully(apkJar.getInputStream(zipEntry));
+ }
+
+ private static byte[] getManifestBytes(StrictJarFile apkJar) throws IOException {
+ ZipEntry zipEntry = apkJar.findEntry(JarFile.MANIFEST_NAME);
+ if (zipEntry == null) {
+ return null;
}
+ return Streams.readFully(apkJar.getInputStream(zipEntry));
}
private static byte[] encodeApkContentDigests(List<Pair<Integer, byte[]>> apkContentDigests) {
@@ -329,6 +414,16 @@ public abstract class SourceStampVerifier {
return result.array();
}
+ private static byte[] computeSha256Digest(byte[] input) {
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+ messageDigest.update(input);
+ return messageDigest.digest();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Failed to find SHA-256", e);
+ }
+ }
+
private static void closeApkJar(StrictJarFile apkJar) {
try {
if (apkJar == null) {
diff --git a/core/java/android/util/apk/TEST_MAPPING b/core/java/android/util/apk/TEST_MAPPING
new file mode 100644
index 000000000000..8544e82e04e0
--- /dev/null
+++ b/core/java/android/util/apk/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.util.apk.SourceStampVerifierTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index b4dae566ce2a..dd48d554f296 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -606,12 +606,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private void updateState(InsetsState newState) {
mState.setDisplayFrame(newState.getDisplayFrame());
- for (int i = newState.getSourcesCount() - 1; i >= 0; i--) {
- InsetsSource source = newState.sourceAt(i);
+ for (int i = 0; i < InsetsState.SIZE; i++) {
+ InsetsSource source = newState.peekSource(i);
+ if (source == null) continue;;
getSourceConsumer(source.getType()).updateSource(source);
}
- for (int i = mState.getSourcesCount() - 1; i >= 0; i--) {
- InsetsSource source = mState.sourceAt(i);
+ for (int i = 0; i < InsetsState.SIZE; i++) {
+ InsetsSource source = mState.peekSource(i);
+ if (source == null) continue;
if (newState.peekSource(source.getType()) == null) {
mState.removeSource(source.getType());
}
@@ -707,7 +709,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (hideTypes[0] != 0) {
applyAnimation(hideTypes[0], false /* show */, false /* fromIme */);
}
- if (hasControl && mRequestedState.getSourcesCount() > 0) {
+ if (hasControl && mRequestedState.hasSources()) {
// We might have changed our requested visibilities while we don't have the control,
// so we need to update our requested state once we have control. Otherwise, our
// requested state at the server side might be incorrect.
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 17620fa3bb4b..9bf2e01a6bd1 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -50,6 +50,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.Objects;
import java.util.StringJoiner;
@@ -117,6 +118,7 @@ public class InsetsState implements Parcelable {
public static final int ITYPE_EXTRA_NAVIGATION_BAR = 15;
static final int LAST_TYPE = ITYPE_EXTRA_NAVIGATION_BAR;
+ public static final int SIZE = LAST_TYPE + 1;
// Derived types
@@ -140,7 +142,7 @@ public class InsetsState implements Parcelable {
static final int ISIDE_FLOATING = 4;
static final int ISIDE_UNKNOWN = 5;
- private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
+ private InsetsSource[] mSources = new InsetsSource[SIZE];
/**
* The frame of the display these sources are relative to.
@@ -177,7 +179,7 @@ public class InsetsState implements Parcelable {
final Rect relativeFrame = new Rect(frame);
final Rect relativeFrameMax = new Rect(frame);
for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
- InsetsSource source = mSources.get(type);
+ InsetsSource source = mSources[type];
if (source == null) {
int index = indexOf(toPublicType(type));
if (typeInsetsMap[index] == null) {
@@ -227,7 +229,7 @@ public class InsetsState implements Parcelable {
public Rect calculateVisibleInsets(Rect frame, @SoftInputModeFlags int softInputMode) {
Insets insets = Insets.NONE;
for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
- InsetsSource source = mSources.get(type);
+ InsetsSource source = mSources[type];
if (source == null) {
continue;
}
@@ -256,7 +258,7 @@ public class InsetsState implements Parcelable {
public int calculateUncontrollableInsetsFromFrame(Rect frame) {
int blocked = 0;
for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
- InsetsSource source = mSources.get(type);
+ InsetsSource source = mSources[type];
if (source == null) {
continue;
}
@@ -350,11 +352,26 @@ public class InsetsState implements Parcelable {
}
public InsetsSource getSource(@InternalInsetsType int type) {
- return mSources.computeIfAbsent(type, InsetsSource::new);
+ InsetsSource source = mSources[type];
+ if (source != null) {
+ return source;
+ }
+ source = new InsetsSource(type);
+ mSources[type] = source;
+ return source;
}
public @Nullable InsetsSource peekSource(@InternalInsetsType int type) {
- return mSources.get(type);
+ return mSources[type];
+ }
+
+ public boolean hasSources() {
+ for (int i = 0; i < SIZE; i++) {
+ if (mSources[i] != null) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -366,7 +383,7 @@ public class InsetsState implements Parcelable {
* doesn't exist.
*/
public boolean getSourceOrDefaultVisibility(@InternalInsetsType int type) {
- final InsetsSource source = mSources.get(type);
+ final InsetsSource source = mSources[type];
return source != null ? source.isVisible() : getDefaultVisibility(type);
}
@@ -385,7 +402,7 @@ public class InsetsState implements Parcelable {
* @param type The {@link InternalInsetsType} of the source to remove
*/
public void removeSource(@InternalInsetsType int type) {
- mSources.remove(type);
+ mSources[type] = null;
}
/**
@@ -395,7 +412,7 @@ public class InsetsState implements Parcelable {
* @param visible {@code true} for visible
*/
public void setSourceVisible(@InternalInsetsType int type, boolean visible) {
- InsetsSource source = mSources.get(type);
+ InsetsSource source = mSources[type];
if (source != null) {
source.setVisible(visible);
}
@@ -407,27 +424,21 @@ public class InsetsState implements Parcelable {
public void set(InsetsState other, boolean copySources) {
mDisplayFrame.set(other.mDisplayFrame);
- mSources.clear();
if (copySources) {
- for (int i = 0; i < other.mSources.size(); i++) {
- InsetsSource source = other.mSources.valueAt(i);
- mSources.put(source.getType(), new InsetsSource(source));
+ for (int i = 0; i < SIZE; i++) {
+ InsetsSource source = other.mSources[i];
+ if (source == null) continue;
+ mSources[i] = new InsetsSource(source);
}
} else {
- mSources.putAll(other.mSources);
+ for (int i = 0; i < SIZE; i++) {
+ mSources[i] = other.mSources[i];
+ }
}
}
public void addSource(InsetsSource source) {
- mSources.put(source.getType(), source);
- }
-
- public int getSourcesCount() {
- return mSources.size();
- }
-
- public InsetsSource sourceAt(int index) {
- return mSources.valueAt(index);
+ mSources[source.getType()] = source;
}
public static @InternalInsetsType ArraySet<Integer> toInternalType(@InsetsType int types) {
@@ -508,8 +519,10 @@ public class InsetsState implements Parcelable {
public void dump(String prefix, PrintWriter pw) {
pw.println(prefix + "InsetsState");
- for (int i = mSources.size() - 1; i >= 0; i--) {
- mSources.valueAt(i).dump(prefix + " ", pw);
+ for (int i = 0; i < SIZE; i++) {
+ InsetsSource source = mSources[i];
+ if (source == null) continue;
+ source.dump(prefix + " ", pw);
}
}
@@ -578,26 +591,16 @@ public class InsetsState implements Parcelable {
if (!mDisplayFrame.equals(state.mDisplayFrame)) {
return false;
}
- int size = mSources.size();
- int otherSize = state.mSources.size();
- if (excludingCaptionInsets) {
- if (mSources.get(ITYPE_CAPTION_BAR) != null) {
- size--;
- }
- if (state.mSources.get(ITYPE_CAPTION_BAR) != null) {
- otherSize--;
- }
- }
- if (size != otherSize) {
- return false;
- }
- for (int i = mSources.size() - 1; i >= 0; i--) {
- InsetsSource source = mSources.valueAt(i);
+ for (int i = 0; i < SIZE; i++) {
if (excludingCaptionInsets) {
- if (source.getType() == ITYPE_CAPTION_BAR) continue;
+ if (i == ITYPE_CAPTION_BAR) continue;
+ }
+ InsetsSource source = mSources[i];
+ InsetsSource otherSource = state.mSources[i];
+ if (source == null && otherSource == null) {
+ continue;
}
- InsetsSource otherSource = state.mSources.get(source.getType());
- if (otherSource == null) {
+ if (source != null && otherSource == null || source == null && otherSource != null) {
return false;
}
if (!otherSource.equals(source, excludeInvisibleImeFrames)) {
@@ -609,7 +612,7 @@ public class InsetsState implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mDisplayFrame, mSources);
+ return Objects.hash(mDisplayFrame, Arrays.hashCode(mSources));
}
public InsetsState(Parcel in) {
@@ -624,10 +627,7 @@ public class InsetsState implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mDisplayFrame, flags);
- dest.writeInt(mSources.size());
- for (int i = 0; i < mSources.size(); i++) {
- dest.writeParcelable(mSources.valueAt(i), flags);
- }
+ dest.writeParcelableArray(mSources, 0);
}
public static final @android.annotation.NonNull Creator<InsetsState> CREATOR = new Creator<InsetsState>() {
@@ -642,19 +642,15 @@ public class InsetsState implements Parcelable {
};
public void readFromParcel(Parcel in) {
- mSources.clear();
mDisplayFrame.set(in.readParcelable(null /* loader */));
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- final InsetsSource source = in.readParcelable(null /* loader */);
- mSources.put(source.getType(), source);
- }
+ mSources = in.readParcelableArray(null, InsetsSource.class);
}
@Override
public String toString() {
StringJoiner joiner = new StringJoiner(", ");
- for (InsetsSource source : mSources.values()) {
+ for (int i = 0; i < SIZE; i++) {
+ InsetsSource source = mSources[i];
if (source != null) {
joiner.add(source.toString());
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index e455155a319e..3b3836582b16 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -49,6 +49,7 @@ import android.os.Build;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Trace;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseIntArray;
@@ -102,6 +103,8 @@ public final class SurfaceControl implements Parcelable {
long otherTransactionObj);
private static native void nativeSetAnimationTransaction(long transactionObj);
private static native void nativeSetEarlyWakeup(long transactionObj);
+ private static native void nativeSetEarlyWakeupStart(long transactionObj);
+ private static native void nativeSetEarlyWakeupEnd(long transactionObj);
private static native void nativeSetLayer(long transactionObj, long nativeObject, int zorder);
private static native void nativeSetRelativeLayer(long transactionObj, long nativeObject,
@@ -437,7 +440,9 @@ public final class SurfaceControl implements Parcelable {
release();
}
if (nativeObject != 0) {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "closeGuard");
mCloseGuard.open("release");
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
mNativeObject = nativeObject;
mNativeHandle = mNativeObject != 0 ? nativeGetHandle(nativeObject) : 0;
@@ -2775,6 +2780,8 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * @deprecated use {@link Transaction#setEarlyWakeupStart()}
+ *
* Indicate that SurfaceFlinger should wake up earlier than usual as a result of this
* transaction. This should be used when the caller thinks that the scene is complex enough
* that it's likely to hit GL composition, and thus, SurfaceFlinger needs to more time in
@@ -2783,11 +2790,35 @@ public final class SurfaceControl implements Parcelable {
* Corresponds to setting ISurfaceComposer::eEarlyWakeup
* @hide
*/
+ @Deprecated
public Transaction setEarlyWakeup() {
nativeSetEarlyWakeup(mNativeObject);
return this;
}
+ /**
+ * Provides a hint to SurfaceFlinger to change its offset so that SurfaceFlinger wakes up
+ * earlier to compose surfaces. The caller should use this as a hint to SurfaceFlinger
+ * when the scene is complex enough to use GPU composition. The hint will remain active
+ * until until the client calls {@link Transaction#setEarlyWakeupEnd}.
+ *
+ * @hide
+ */
+ public Transaction setEarlyWakeupStart() {
+ nativeSetEarlyWakeupStart(mNativeObject);
+ return this;
+ }
+
+ /**
+ * Removes the early wake up hint set by {@link Transaction#setEarlyWakeupStart}.
+ *
+ * @hide
+ */
+ public Transaction setEarlyWakeupEnd() {
+ nativeSetEarlyWakeupEnd(mNativeObject);
+ return this;
+ }
+
/**
* Sets an arbitrary piece of metadata on the surface. This is a helper for int data.
* @hide
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 809a9cfde587..90e1eab09fd6 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -640,7 +640,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mTmpRect.set(0, 0, mSurfaceWidth, mSurfaceHeight);
}
SyncRtSurfaceTransactionApplier applier = new SyncRtSurfaceTransactionApplier(this);
- applier.scheduleApply(false /* earlyWakeup */,
+ applier.scheduleApply(
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(mSurfaceControl)
.withWindowCrop(mTmpRect)
.build());
diff --git a/core/java/android/view/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
index 9c97f3e5b503..062285ff2f5d 100644
--- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java
+++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
@@ -53,11 +53,10 @@ public class SyncRtSurfaceTransactionApplier {
/**
* Schedules applying surface parameters on the next frame.
*
- * @param earlyWakeup Whether to set {@link Transaction#setEarlyWakeup()} on transaction.
* @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
* this method to avoid synchronization issues.
*/
- public void scheduleApply(boolean earlyWakeup, final SurfaceParams... params) {
+ public void scheduleApply(final SurfaceParams... params) {
if (mTargetViewRootImpl == null) {
return;
}
@@ -67,7 +66,7 @@ public class SyncRtSurfaceTransactionApplier {
return;
}
Transaction t = new Transaction();
- applyParams(t, frame, earlyWakeup, params);
+ applyParams(t, frame, params);
});
// Make sure a frame gets scheduled.
@@ -78,12 +77,10 @@ public class SyncRtSurfaceTransactionApplier {
* Applies surface parameters on the next frame.
* @param t transaction to apply all parameters in.
* @param frame frame to synchronize to. Set -1 when sync is not required.
- * @param earlyWakeup Whether to set {@link Transaction#setEarlyWakeup()} on transaction.
* @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
* this method to avoid synchronization issues.
*/
- void applyParams(Transaction t, long frame, boolean earlyWakeup,
- final SurfaceParams... params) {
+ void applyParams(Transaction t, long frame, final SurfaceParams... params) {
for (int i = params.length - 1; i >= 0; i--) {
SurfaceParams surfaceParams = params[i];
SurfaceControl surface = surfaceParams.surface;
@@ -92,9 +89,6 @@ public class SyncRtSurfaceTransactionApplier {
}
applyParams(t, surfaceParams, mTmpFloat9);
}
- if (earlyWakeup) {
- t.setEarlyWakeup();
- }
t.apply();
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8b5d033072fb..2743654695e0 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -22,6 +22,7 @@ import static android.view.InputDevice.SOURCE_CLASS_NONE;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.LAST_TYPE;
+import static android.view.InsetsState.SIZE;
import static android.view.View.PFLAG_DRAW_ANIMATION;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -564,7 +565,7 @@ public final class ViewRootImpl implements ViewParent,
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
boolean mPendingAlwaysConsumeSystemBars;
private final InsetsState mTempInsets = new InsetsState();
- private final InsetsSourceControl[] mTempControls = new InsetsSourceControl[LAST_TYPE + 1];
+ private final InsetsSourceControl[] mTempControls = new InsetsSourceControl[SIZE];
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 686d561a1a5a..31a44023b036 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -120,13 +120,12 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host {
mApplier = new SyncRtSurfaceTransactionApplier(mViewRoot.mView);
}
if (mViewRoot.mView.isHardwareAccelerated()) {
- mApplier.scheduleApply(false /* earlyWakeup */, params);
+ mApplier.scheduleApply(params);
} else {
// Window doesn't support hardware acceleration, no synchronization for now.
// TODO(b/149342281): use mViewRoot.mSurface.getNextFrameNumber() to sync on every
// frame instead.
- mApplier.applyParams(new SurfaceControl.Transaction(), -1 /* frame */,
- false /* earlyWakeup */, params);
+ mApplier.applyParams(new SurfaceControl.Transaction(), -1 /* frame */, params);
}
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 6eb71f747be6..c43beea98c7e 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -52,6 +52,7 @@ import android.view.contentcapture.ViewNode.ViewStructureImpl;
import com.android.internal.os.IResultReceiver;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -146,7 +147,44 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
* Binder object used to update the session state.
*/
@NonNull
- private final IResultReceiver.Stub mSessionStateReceiver;
+ private final SessionStateReceiver mSessionStateReceiver;
+
+ private static class SessionStateReceiver extends IResultReceiver.Stub {
+ private final WeakReference<MainContentCaptureSession> mMainSession;
+
+ SessionStateReceiver(MainContentCaptureSession session) {
+ mMainSession = new WeakReference<>(session);
+ }
+
+ @Override
+ public void send(int resultCode, Bundle resultData) {
+ final MainContentCaptureSession mainSession = mMainSession.get();
+ if (mainSession == null) {
+ Log.w(TAG, "received result after mina session released");
+ return;
+ }
+ final IBinder binder;
+ if (resultData != null) {
+ // Change in content capture enabled.
+ final boolean hasEnabled = resultData.getBoolean(EXTRA_ENABLED_STATE);
+ if (hasEnabled) {
+ final boolean disabled = (resultCode == RESULT_CODE_FALSE);
+ mainSession.mDisabled.set(disabled);
+ return;
+ }
+ binder = resultData.getBinder(EXTRA_BINDER);
+ if (binder == null) {
+ Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result");
+ mainSession.mHandler.post(() -> mainSession.resetSession(
+ STATE_DISABLED | STATE_INTERNAL_ERROR));
+ return;
+ }
+ } else {
+ binder = null;
+ }
+ mainSession.mHandler.post(() -> mainSession.onSessionStarted(resultCode, binder));
+ }
+ }
protected MainContentCaptureSession(@NonNull Context context,
@NonNull ContentCaptureManager manager, @NonNull Handler handler,
@@ -159,32 +197,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
final int logHistorySize = mManager.mOptions.logHistorySize;
mFlushHistory = logHistorySize > 0 ? new LocalLog(logHistorySize) : null;
- mSessionStateReceiver = new IResultReceiver.Stub() {
- @Override
- public void send(int resultCode, Bundle resultData) {
- final IBinder binder;
- if (resultData != null) {
- // Change in content capture enabled.
- final boolean hasEnabled = resultData.getBoolean(EXTRA_ENABLED_STATE);
- if (hasEnabled) {
- final boolean disabled = (resultCode == RESULT_CODE_FALSE);
- mDisabled.set(disabled);
- return;
- }
- binder = resultData.getBinder(EXTRA_BINDER);
- if (binder == null) {
- Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result");
- mHandler.post(() -> resetSession(
- STATE_DISABLED | STATE_INTERNAL_ERROR));
- return;
- }
- } else {
- binder = null;
- }
- mHandler.post(() -> onSessionStarted(resultCode, binder));
- }
- };
-
+ mSessionStateReceiver = new SessionStateReceiver(this);
}
@Override
@@ -543,6 +556,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
Log.e(TAG, "Error destroying system-service session " + mId + " for "
+ getDebugState() + ": " + e);
}
+
+ if (mDirectServiceInterface != null) {
+ mDirectServiceInterface.asBinder().unlinkToDeath(mDirectServiceVulture, 0);
+ }
+ mDirectServiceInterface = null;
}
// TODO(b/122454205): once we support multiple sessions, we might need to move some of these
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 2679c69be4f6..fb5d55dd2141 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -27,7 +27,6 @@ import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -90,7 +89,7 @@ public class ToastPresenter {
// context to it. This is problematic for multi-user because callers can pass a context
// created via Context.createContextAsUser().
mAccessibilityManager = new AccessibilityManager(context, accessibilityManager,
- UserHandle.getCallingUserId());
+ context.getUserId());
mParams = createLayoutParams();
}
diff --git a/core/java/android/widget/inline/InlineContentView.java b/core/java/android/widget/inline/InlineContentView.java
index 6a85de5ca757..8ca218c1d1a7 100644
--- a/core/java/android/widget/inline/InlineContentView.java
+++ b/core/java/android/widget/inline/InlineContentView.java
@@ -27,6 +27,7 @@ import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnPreDrawListener;
import java.util.function.Consumer;
@@ -130,6 +131,16 @@ public class InlineContentView extends ViewGroup {
@Nullable
private SurfacePackageUpdater mSurfacePackageUpdater;
+ @NonNull
+ private final OnPreDrawListener mDrawListener = new OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ int visibility = InlineContentView.this.isShown() ? VISIBLE : GONE;
+ mSurfaceView.setVisibility(visibility);
+ return true;
+ }
+ };
+
/**
* @inheritDoc
* @hide
@@ -202,6 +213,8 @@ public class InlineContentView extends ViewGroup {
}
});
}
+ mSurfaceView.setVisibility(VISIBLE);
+ getViewTreeObserver().addOnPreDrawListener(mDrawListener);
}
@Override
@@ -211,6 +224,7 @@ public class InlineContentView extends ViewGroup {
if (mSurfacePackageUpdater != null) {
mSurfacePackageUpdater.onSurfacePackageReleased();
}
+ getViewTreeObserver().removeOnPreDrawListener(mDrawListener);
}
@Override
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index e0b67da3bcd4..dc4c8fd76e8e 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -195,6 +195,7 @@ public class ChooserActivity extends ResolverActivity implements
private boolean mIsAppPredictorComponentAvailable;
private Map<ChooserTarget, AppTarget> mDirectShareAppTargetCache;
private Map<ChooserTarget, ShortcutInfo> mDirectShareShortcutInfoCache;
+ private Map<ComponentName, ComponentName> mChooserTargetComponentNameCache;
public static final int TARGET_TYPE_DEFAULT = 0;
public static final int TARGET_TYPE_CHOOSER_TARGET = 1;
@@ -511,6 +512,11 @@ public class ChooserActivity extends ResolverActivity implements
adapterForUserHandle.addServiceResults(sri.originalTarget,
sri.resultTargets, TARGET_TYPE_CHOOSER_TARGET,
/* directShareShortcutInfoCache */ null, mServiceConnections);
+ if (!sri.resultTargets.isEmpty() && sri.originalTarget != null) {
+ mChooserTargetComponentNameCache.put(
+ sri.resultTargets.get(0).getComponentName(),
+ sri.originalTarget.getResolvedComponentName());
+ }
}
}
unbindService(sri.connection);
@@ -772,6 +778,7 @@ public class ChooserActivity extends ResolverActivity implements
target.getAction()
);
mDirectShareShortcutInfoCache = new HashMap<>();
+ mChooserTargetComponentNameCache = new HashMap<>();
}
@Override
@@ -2242,15 +2249,18 @@ public class ChooserActivity extends ResolverActivity implements
List<AppTargetId> targetIds = new ArrayList<>();
for (ChooserTargetInfo chooserTargetInfo : surfacedTargetInfo) {
ChooserTarget chooserTarget = chooserTargetInfo.getChooserTarget();
- String componentName = chooserTarget.getComponentName().flattenToString();
+ ComponentName componentName = mChooserTargetComponentNameCache.getOrDefault(
+ chooserTarget.getComponentName(), chooserTarget.getComponentName());
if (mDirectShareShortcutInfoCache.containsKey(chooserTarget)) {
String shortcutId = mDirectShareShortcutInfoCache.get(chooserTarget).getId();
targetIds.add(new AppTargetId(
- String.format("%s/%s/%s", shortcutId, componentName, SHORTCUT_TARGET)));
+ String.format("%s/%s/%s", shortcutId, componentName.flattenToString(),
+ SHORTCUT_TARGET)));
} else {
String titleHash = ChooserUtil.md5(chooserTarget.getTitle().toString());
targetIds.add(new AppTargetId(
- String.format("%s/%s/%s", titleHash, componentName, CHOOSER_TARGET)));
+ String.format("%s/%s/%s", titleHash, componentName.flattenToString(),
+ CHOOSER_TARGET)));
}
}
directShareAppPredictor.notifyLaunchLocationShown(LAUNCH_LOCATION_DIRECT_SHARE, targetIds);
@@ -2272,7 +2282,8 @@ public class ChooserActivity extends ResolverActivity implements
}
if (mChooserTargetRankingEnabled && appTarget == null) {
// Send ChooserTarget sharing info to AppPredictor.
- ComponentName componentName = chooserTarget.getComponentName();
+ ComponentName componentName = mChooserTargetComponentNameCache.getOrDefault(
+ chooserTarget.getComponentName(), chooserTarget.getComponentName());
try {
appTarget = new AppTarget.Builder(
new AppTargetId(componentName.flattenToString()),
@@ -2800,17 +2811,7 @@ public class ChooserActivity extends ResolverActivity implements
|| chooserListAdapter.mDisplayList.isEmpty()) {
chooserListAdapter.notifyDataSetChanged();
} else {
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... voids) {
- chooserListAdapter.updateAlphabeticalList();
- return null;
- }
- @Override
- protected void onPostExecute(Void aVoid) {
- chooserListAdapter.notifyDataSetChanged();
- }
- }.execute();
+ chooserListAdapter.updateAlphabeticalList();
}
// don't support direct share on low ram devices
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index d6ff7b13c934..5efd46c4c64a 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -275,33 +275,43 @@ public class ChooserListAdapter extends ResolverListAdapter {
}
void updateAlphabeticalList() {
- mSortedList.clear();
- List<DisplayResolveInfo> tempList = new ArrayList<>();
- tempList.addAll(mDisplayList);
- tempList.addAll(mCallerTargets);
- if (mEnableStackedApps) {
- // Consolidate multiple targets from same app.
- Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
- for (DisplayResolveInfo info : tempList) {
- String packageName = info.getResolvedComponentName().getPackageName();
- DisplayResolveInfo multiDri = consolidated.get(packageName);
- if (multiDri == null) {
- consolidated.put(packageName, info);
- } else if (multiDri instanceof MultiDisplayResolveInfo) {
- ((MultiDisplayResolveInfo) multiDri).addTarget(info);
- } else {
- // create consolidated target from the single DisplayResolveInfo
- MultiDisplayResolveInfo multiDisplayResolveInfo =
+ new AsyncTask<Void, Void, List<DisplayResolveInfo>>() {
+ @Override
+ protected List<DisplayResolveInfo> doInBackground(Void... voids) {
+ List<DisplayResolveInfo> allTargets = new ArrayList<>();
+ allTargets.addAll(mDisplayList);
+ allTargets.addAll(mCallerTargets);
+ if (!mEnableStackedApps) {
+ return allTargets;
+ }
+ // Consolidate multiple targets from same app.
+ Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
+ for (DisplayResolveInfo info : allTargets) {
+ String packageName = info.getResolvedComponentName().getPackageName();
+ DisplayResolveInfo multiDri = consolidated.get(packageName);
+ if (multiDri == null) {
+ consolidated.put(packageName, info);
+ } else if (multiDri instanceof MultiDisplayResolveInfo) {
+ ((MultiDisplayResolveInfo) multiDri).addTarget(info);
+ } else {
+ // create consolidated target from the single DisplayResolveInfo
+ MultiDisplayResolveInfo multiDisplayResolveInfo =
new MultiDisplayResolveInfo(packageName, multiDri);
- multiDisplayResolveInfo.addTarget(info);
- consolidated.put(packageName, multiDisplayResolveInfo);
+ multiDisplayResolveInfo.addTarget(info);
+ consolidated.put(packageName, multiDisplayResolveInfo);
+ }
}
+ List<DisplayResolveInfo> groupedTargets = new ArrayList<>();
+ groupedTargets.addAll(consolidated.values());
+ Collections.sort(groupedTargets, new ChooserActivity.AzInfoComparator(mContext));
+ return groupedTargets;
}
- mSortedList.addAll(consolidated.values());
- } else {
- mSortedList.addAll(tempList);
- }
- Collections.sort(mSortedList, new ChooserActivity.AzInfoComparator(mContext));
+ @Override
+ protected void onPostExecute(List<DisplayResolveInfo> newList) {
+ mSortedList = newList;
+ notifyDataSetChanged();
+ }
+ }.execute();
}
@Override
@@ -828,6 +838,12 @@ public class ChooserListAdapter extends ResolverListAdapter {
return mServiceTargets.get(value).getChooserTarget();
}
+ protected boolean alwaysShowSubLabel() {
+ // Always show a subLabel for visual consistency across list items. Show an empty
+ // subLabel if the subLabel is the same as the label
+ return true;
+ }
+
/**
* Rather than fully sorting the input list, this sorting task will put the top k elements
* in the head of input list and fill the tail with other elements in undetermined order.
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index fc8cafdc526c..094fb1e2f23c 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -540,7 +540,7 @@ public class ResolverListAdapter extends BaseAdapter {
&& !((DisplayResolveInfo) info).hasDisplayLabel()) {
getLoadLabelTask((DisplayResolveInfo) info, holder).execute();
} else {
- holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo());
+ holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel());
if (info instanceof SelectableTargetInfo) {
// direct share targets should append the application name for a better readout
DisplayResolveInfo rInfo = ((SelectableTargetInfo) info).getDisplayResolveInfo();
@@ -642,6 +642,10 @@ public class ResolverListAdapter extends BaseAdapter {
mIsTabLoaded = true;
}
+ protected boolean alwaysShowSubLabel() {
+ return false;
+ }
+
/**
* Necessary methods to communicate between {@link ResolverListAdapter}
* and {@link ResolverActivity}.
@@ -684,20 +688,18 @@ public class ResolverListAdapter extends BaseAdapter {
icon = (ImageView) view.findViewById(R.id.icon);
}
- public void bindLabel(CharSequence label, CharSequence subLabel) {
- if (!TextUtils.equals(text.getText(), label)) {
- text.setText(label);
- }
+ public void bindLabel(CharSequence label, CharSequence subLabel, boolean showSubLabel) {
+ text.setText(label);
- // Always show a subLabel for visual consistency across list items. Show an empty
- // subLabel if the subLabel is the same as the label
if (TextUtils.equals(label, subLabel)) {
subLabel = null;
}
- if (!TextUtils.equals(text2.getText(), subLabel)) {
+ text2.setText(subLabel);
+ if (showSubLabel || subLabel != null) {
text2.setVisibility(View.VISIBLE);
- text2.setText(subLabel);
+ } else {
+ text2.setVisibility(View.GONE);
}
itemView.setContentDescription(null);
@@ -754,7 +756,7 @@ public class ResolverListAdapter extends BaseAdapter {
protected void onPostExecute(CharSequence[] result) {
mDisplayResolveInfo.setDisplayLabel(result[0]);
mDisplayResolveInfo.setExtendedInfo(result[1]);
- mHolder.bindLabel(result[0], result[1]);
+ mHolder.bindLabel(result[0], result[1], alwaysShowSubLabel());
}
}
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java
index ab0cc3093b6d..2393036b5a38 100644
--- a/core/java/com/android/internal/os/FuseAppLoop.java
+++ b/core/java/com/android/internal/os/FuseAppLoop.java
@@ -210,7 +210,7 @@ public class FuseAppLoop implements Handler.Callback {
if (mInstance != 0) {
native_replySimple(mInstance, unique, FUSE_OK);
}
- mBytesMap.stopUsing(entry.getThreadId());
+ mBytesMap.stopUsing(inode);
recycleLocked(args);
}
break;
@@ -270,7 +270,7 @@ public class FuseAppLoop implements Handler.Callback {
if (mInstance != 0) {
native_replyOpen(mInstance, unique, /* fh */ inode);
entry.opened = true;
- return mBytesMap.startUsing(entry.getThreadId());
+ return mBytesMap.startUsing(inode);
}
} catch (ErrnoException error) {
replySimpleLocked(unique, getError(error));
@@ -354,27 +354,27 @@ public class FuseAppLoop implements Handler.Callback {
}
/**
- * Map between Thread ID and byte buffer.
+ * Map between inode and byte buffer.
*/
private static class BytesMap {
final Map<Long, BytesMapEntry> mEntries = new HashMap<>();
- byte[] startUsing(long threadId) {
- BytesMapEntry entry = mEntries.get(threadId);
+ byte[] startUsing(long inode) {
+ BytesMapEntry entry = mEntries.get(inode);
if (entry == null) {
entry = new BytesMapEntry();
- mEntries.put(threadId, entry);
+ mEntries.put(inode, entry);
}
entry.counter++;
return entry.bytes;
}
- void stopUsing(long threadId) {
- final BytesMapEntry entry = mEntries.get(threadId);
+ void stopUsing(long inode) {
+ final BytesMapEntry entry = mEntries.get(inode);
Objects.requireNonNull(entry);
entry.counter--;
if (entry.counter <= 0) {
- mEntries.remove(threadId);
+ mEntries.remove(inode);
}
}
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java b/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java
index c11b939098c4..69ca9922e81f 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java
@@ -59,7 +59,7 @@ import java.util.Objects;
* #getProcessCpuUsageDiffed()} result.
*
* <p>Thresholding is done in this class, instead of {@link KernelCpuThreadReader}, and instead of
- * WestWorld, because the thresholding should be done after diffing, not before. This is because of
+ * statsd, because the thresholding should be done after diffing, not before. This is because of
* two issues with thresholding before diffing:
*
* <ul>
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 505a05eb9c23..a7d9827855a2 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -24,6 +24,7 @@ import android.content.pm.ApplicationInfo;
import android.net.Credentials;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
+import android.net.NetworkUtils;
import android.os.FactoryTest;
import android.os.IVold;
import android.os.Process;
@@ -286,6 +287,13 @@ public final class Zygote {
private Zygote() {}
+ private static boolean containsInetGid(int[] gids) {
+ for (int i = 0; i < gids.length; i++) {
+ if (gids[i] == android.os.Process.INET_GID) return true;
+ }
+ return false;
+ }
+
/**
* Forks a new VM instance. The current VM must have been started
* with the -Xzygote flag. <b>NOTE: new instance keeps all
@@ -341,6 +349,11 @@ public final class Zygote {
if (pid == 0) {
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
+
+ // If no GIDs were specified, don't make any permissions changes based on groups.
+ if (gids != null && gids.length > 0) {
+ NetworkUtils.setAllowNetworkingForProcess(containsInetGid(gids));
+ }
}
// Set the Java Language thread priority to the default value for new apps.
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 7bfed91c42b9..6fe1d8140371 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -16,6 +16,7 @@
package com.android.internal.policy;
+import android.graphics.Insets;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RenderNode;
@@ -69,16 +70,14 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
private ColorDrawable mNavigationBarColor;
private boolean mOldFullscreen;
private boolean mFullscreen;
- private final Rect mOldSystemInsets = new Rect();
- private final Rect mOldStableInsets = new Rect();
- private final Rect mSystemInsets = new Rect();
- private final Rect mStableInsets = new Rect();
+ private final Rect mOldSystemBarInsets = new Rect();
+ private final Rect mSystemBarInsets = new Rect();
private final Rect mTmpRect = new Rect();
public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
Drawable userCaptionBackgroundDrawable, int statusBarColor, int navigationBarColor,
- boolean fullscreen, Rect systemInsets, Rect stableInsets) {
+ boolean fullscreen, Insets systemBarInsets) {
setName("ResizeFrame");
mRenderer = renderer;
@@ -95,10 +94,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
mTargetRect.set(initialBounds);
mFullscreen = fullscreen;
mOldFullscreen = fullscreen;
- mSystemInsets.set(systemInsets);
- mStableInsets.set(stableInsets);
- mOldSystemInsets.set(systemInsets);
- mOldStableInsets.set(stableInsets);
+ mSystemBarInsets.set(systemBarInsets.toRect());
+ mOldSystemBarInsets.set(systemBarInsets.toRect());
// Kick off our draw thread.
start();
@@ -154,16 +151,13 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
*
* @param newTargetBounds The new target bounds.
* @param fullscreen Whether the window is currently drawing in fullscreen.
- * @param systemInsets The current visible system insets for the window.
- * @param stableInsets The stable insets for the window.
+ * @param systemBarInsets The current visible system insets for the window.
*/
- public void setTargetRect(Rect newTargetBounds, boolean fullscreen, Rect systemInsets,
- Rect stableInsets) {
+ public void setTargetRect(Rect newTargetBounds, boolean fullscreen, Rect systemBarInsets) {
synchronized (this) {
mFullscreen = fullscreen;
mTargetRect.set(newTargetBounds);
- mSystemInsets.set(systemInsets);
- mStableInsets.set(stableInsets);
+ mSystemBarInsets.set(systemBarInsets);
// Notify of a bounds change.
pingRenderLocked(false /* drawImmediate */);
}
@@ -247,14 +241,12 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
mNewTargetRect.set(mTargetRect);
if (!mNewTargetRect.equals(mOldTargetRect)
|| mOldFullscreen != mFullscreen
- || !mStableInsets.equals(mOldStableInsets)
- || !mSystemInsets.equals(mOldSystemInsets)
+ || !mSystemBarInsets.equals(mOldSystemBarInsets)
|| mReportNextDraw) {
mOldFullscreen = mFullscreen;
mOldTargetRect.set(mNewTargetRect);
- mOldSystemInsets.set(mSystemInsets);
- mOldStableInsets.set(mStableInsets);
- redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets);
+ mOldSystemBarInsets.set(mSystemBarInsets);
+ redrawLocked(mNewTargetRect, mFullscreen);
}
}
@@ -304,11 +296,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
*
* @param newBounds The window bounds which needs to be drawn.
* @param fullscreen Whether the window is currently drawing in fullscreen.
- * @param systemInsets The current visible system insets for the window.
- * @param stableInsets The stable insets for the window.
*/
- private void redrawLocked(Rect newBounds, boolean fullscreen, Rect systemInsets,
- Rect stableInsets) {
+ private void redrawLocked(Rect newBounds, boolean fullscreen) {
// While a configuration change is taking place the view hierarchy might become
// inaccessible. For that case we remember the previous metrics to avoid flashes.
@@ -355,7 +344,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
}
mFrameAndBackdropNode.endRecording();
- drawColorViews(left, top, width, height, fullscreen, systemInsets, stableInsets);
+ drawColorViews(left, top, width, height, fullscreen);
// We need to render the node explicitly
mRenderer.drawRenderNode(mFrameAndBackdropNode);
@@ -363,14 +352,13 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
reportDrawIfNeeded();
}
- private void drawColorViews(int left, int top, int width, int height,
- boolean fullscreen, Rect systemInsets, Rect stableInsets) {
+ private void drawColorViews(int left, int top, int width, int height, boolean fullscreen) {
if (mSystemBarBackgroundNode == null) {
return;
}
RecordingCanvas canvas = mSystemBarBackgroundNode.beginRecording(width, height);
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
- final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
+ final int topInset = mSystemBarInsets.top;
if (mStatusBarColor != null) {
mStatusBarColor.setBounds(0, 0, left + width, topInset);
mStatusBarColor.draw(canvas);
@@ -380,7 +368,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
// don't want the navigation bar background be moving around when resizing in docked mode.
// However, we need it for the transitions into/out of docked mode.
if (mNavigationBarColor != null && fullscreen) {
- DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect, 1f);
+ DecorView.getNavigationBarRect(width, height, mSystemBarInsets, mTmpRect, 1f);
mNavigationBarColor.setBounds(mTmpRect);
mNavigationBarColor.draw(canvas);
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index c6135f2c81d3..b12c5e9ba5b0 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1050,22 +1050,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
return false;
}
- public static int getColorViewTopInset(int stableTop, int systemTop) {
- return Math.min(stableTop, systemTop);
- }
-
- public static int getColorViewBottomInset(int stableBottom, int systemBottom) {
- return Math.min(stableBottom, systemBottom);
- }
-
- public static int getColorViewRightInset(int stableRight, int systemRight) {
- return Math.min(stableRight, systemRight);
- }
-
- public static int getColorViewLeftInset(int stableLeft, int systemLeft) {
- return Math.min(stableLeft, systemLeft);
- }
-
public static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
return bottomInset == 0 && rightInset > 0;
}
@@ -1079,14 +1063,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
: isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset;
}
- public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect stableInsets,
- Rect contentInsets, Rect outRect, float scale) {
- final int bottomInset =
- (int) (getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom) * scale);
- final int leftInset =
- (int) (getColorViewLeftInset(stableInsets.left, contentInsets.left) * scale);
- final int rightInset =
- (int) (getColorViewLeftInset(stableInsets.right, contentInsets.right) * scale);
+ public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect systemBarInsets,
+ Rect outRect, float scale) {
+ final int bottomInset = (int) (systemBarInsets.bottom * scale);
+ final int leftInset = (int) (systemBarInsets.left * scale);
+ final int rightInset = (int) (systemBarInsets.right * scale);
final int size = getNavBarSize(bottomInset, rightInset, leftInset);
if (isNavBarToRightEdge(bottomInset, rightInset)) {
outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
@@ -1113,31 +1094,30 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
mLastWindowFlags = attrs.flags;
if (insets != null) {
- mLastTopInset = getColorViewTopInset(insets.getStableInsetTop(),
- insets.getSystemWindowInsetTop());
- mLastBottomInset = getColorViewBottomInset(insets.getStableInsetBottom(),
- insets.getSystemWindowInsetBottom());
- mLastRightInset = getColorViewRightInset(insets.getStableInsetRight(),
- insets.getSystemWindowInsetRight());
- mLastLeftInset = getColorViewRightInset(insets.getStableInsetLeft(),
- insets.getSystemWindowInsetLeft());
+ final Insets systemBarInsets = insets.getInsets(WindowInsets.Type.systemBars());
+ final Insets stableBarInsets = insets.getInsetsIgnoringVisibility(
+ WindowInsets.Type.systemBars());
+ mLastTopInset = systemBarInsets.top;
+ mLastBottomInset = systemBarInsets.bottom;
+ mLastRightInset = systemBarInsets.right;
+ mLastLeftInset = systemBarInsets.left;
// Don't animate if the presence of stable insets has changed, because that
// indicates that the window was either just added and received them for the
// first time, or the window size or position has changed.
- boolean hasTopStableInset = insets.getStableInsetTop() != 0;
+ boolean hasTopStableInset = stableBarInsets.top != 0;
disallowAnimate |= (hasTopStableInset != mLastHasTopStableInset);
mLastHasTopStableInset = hasTopStableInset;
- boolean hasBottomStableInset = insets.getStableInsetBottom() != 0;
+ boolean hasBottomStableInset = stableBarInsets.bottom != 0;
disallowAnimate |= (hasBottomStableInset != mLastHasBottomStableInset);
mLastHasBottomStableInset = hasBottomStableInset;
- boolean hasRightStableInset = insets.getStableInsetRight() != 0;
+ boolean hasRightStableInset = stableBarInsets.right != 0;
disallowAnimate |= (hasRightStableInset != mLastHasRightStableInset);
mLastHasRightStableInset = hasRightStableInset;
- boolean hasLeftStableInset = insets.getStableInsetLeft() != 0;
+ boolean hasLeftStableInset = stableBarInsets.left != 0;
disallowAnimate |= (hasLeftStableInset != mLastHasLeftStableInset);
mLastHasLeftStableInset = hasLeftStableInset;
@@ -2296,7 +2276,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
Rect stableInsets) {
if (mBackdropFrameRenderer != null) {
- mBackdropFrameRenderer.setTargetRect(newBounds, fullscreen, systemInsets, stableInsets);
+ mBackdropFrameRenderer.setTargetRect(newBounds, fullscreen, systemInsets);
}
}
@@ -2314,11 +2294,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
final ThreadedRenderer renderer = getThreadedRenderer();
if (renderer != null) {
loadBackgroundDrawablesIfNeeded();
+ WindowInsets rootInsets = getRootWindowInsets();
mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
- getCurrentColor(mNavigationColorViewState), fullscreen, systemInsets,
- stableInsets);
+ getCurrentColor(mNavigationColorViewState), fullscreen,
+ rootInsets.getInsets(WindowInsets.Type.systemBars()));
// Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
// If we want to get the shadow shown while resizing, we would need to elevate a new
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index 575a5320bbd3..527286cf000e 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -104,17 +104,18 @@ public class DividerSnapAlgorithm {
public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
boolean isHorizontalDivision, Rect insets) {
this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets,
- DOCKED_INVALID, false);
+ DOCKED_INVALID, false /* minimized */, true /* resizable */);
}
public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
boolean isHorizontalDivision, Rect insets, int dockSide) {
this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets,
- dockSide, false);
+ dockSide, false /* minimized */, true /* resizable */);
}
public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
- boolean isHorizontalDivision, Rect insets, int dockSide, boolean isMinimizedMode) {
+ boolean isHorizontalDivision, Rect insets, int dockSide, boolean isMinimizedMode,
+ boolean isHomeResizable) {
mMinFlingVelocityPxPerSecond =
MIN_FLING_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density;
mMinDismissVelocityPxPerSecond =
@@ -132,8 +133,8 @@ public class DividerSnapAlgorithm {
com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1);
mMinimalSizeResizableTask = res.getDimensionPixelSize(
com.android.internal.R.dimen.default_minimal_size_resizable_task);
- mTaskHeightInMinimizedMode = res.getDimensionPixelSize(
- com.android.internal.R.dimen.task_height_of_minimized_mode);
+ mTaskHeightInMinimizedMode = isHomeResizable ? res.getDimensionPixelSize(
+ com.android.internal.R.dimen.task_height_of_minimized_mode) : 0;
calculateTargets(isHorizontalDivision, dockSide);
mFirstSplitTarget = mTargets.get(1);
mLastSplitTarget = mTargets.get(mTargets.size() - 2);
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index b64923fb5bf8..5d4407bf8370 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -233,13 +233,20 @@ public class ConversationLayout extends FrameLayout
oldVisibility = mImportanceRingView.getVisibility();
wasGone = oldVisibility == GONE;
visibility = !mImportantConversation ? GONE : visibility;
- isGone = visibility == GONE;
- if (wasGone != isGone) {
+ boolean isRingGone = visibility == GONE;
+ if (wasGone != isRingGone) {
// Keep the badge visibility in sync with the icon. This is necessary in cases
// Where the icon is being hidden externally like in group children.
mImportanceRingView.animate().cancel();
mImportanceRingView.setVisibility(visibility);
}
+
+ oldVisibility = mConversationIconBadge.getVisibility();
+ wasGone = oldVisibility == GONE;
+ if (wasGone != isGone) {
+ mConversationIconBadge.animate().cancel();
+ mConversationIconBadge.setVisibility(visibility);
+ }
});
// When the small icon is gone, hide the rest of the badge
mIcon.setOnForceHiddenChangedListener((forceHidden) -> {
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 53272f7eebf9..f312d1d4f25d 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -42,6 +42,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
+import android.widget.TextView;
import com.android.internal.R;
@@ -109,6 +110,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
private ViewGroup mMessagingIconContainer;
private int mConversationContentStart;
private int mNonConversationMarginEnd;
+ private int mNotificationTextMarginTop;
public MessagingGroup(@NonNull Context context) {
super(context);
@@ -148,6 +150,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
R.dimen.conversation_content_start);
mNonConversationMarginEnd = getResources().getDimensionPixelSize(
R.dimen.messaging_layout_margin_end);
+ mNotificationTextMarginTop = getResources().getDimensionPixelSize(
+ R.dimen.notification_text_margin_top);
}
public void updateClipRect() {
@@ -612,7 +616,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
return 0;
}
- public View getSenderView() {
+ public TextView getSenderView() {
return mSenderView;
}
@@ -664,10 +668,14 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
public void setSingleLine(boolean singleLine) {
if (singleLine != mSingleLine) {
mSingleLine = singleLine;
+ MarginLayoutParams p = (MarginLayoutParams) mMessageContainer.getLayoutParams();
+ p.topMargin = singleLine ? 0 : mNotificationTextMarginTop;
+ mMessageContainer.setLayoutParams(p);
mContentContainer.setOrientation(
singleLine ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
MarginLayoutParams layoutParams = (MarginLayoutParams) mSenderView.getLayoutParams();
layoutParams.setMarginEnd(singleLine ? mSenderTextPaddingSingleLine : 0);
+ mSenderView.setSingleLine(singleLine);
updateMaxDisplayedLines();
updateClipRect();
updateSenderVisibility();
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index ac04862d9a7d..4ee647a42116 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -300,6 +300,27 @@ public class MessagingLinearLayout extends ViewGroup {
return mMessagingLayout;
}
+ @Override
+ public int getBaseline() {
+ // When placed in a horizontal linear layout (as is the case in a single-line MessageGroup),
+ // align with the last visible child (which is the one that will be displayed in the single-
+ // line group.
+ int childCount = getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ final View child = getChildAt(i);
+ if (isGone(child)) {
+ continue;
+ }
+ final int childBaseline = child.getBaseline();
+ if (childBaseline == -1) {
+ return -1;
+ }
+ MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
+ return lp.topMargin + childBaseline;
+ }
+ return super.getBaseline();
+ }
+
public interface MessagingChild {
int MEASURED_NORMAL = 0;
int MEASURED_SHORTENED = 1;
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index d9ca9c2f87f5..ea390cd71e31 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -24,6 +24,7 @@ import android.content.ComponentName;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.CarrierAssociatedAppEntry;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
@@ -198,8 +199,8 @@ public class SystemConfig {
// These are the packages of carrier-associated apps which should be disabled until used until
// a SIM is inserted which grants carrier privileges to that carrier app.
- final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps =
- new ArrayMap<>();
+ final ArrayMap<String, List<CarrierAssociatedAppEntry>>
+ mDisabledUntilUsedPreinstalledCarrierAssociatedApps = new ArrayMap<>();
final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
@@ -331,7 +332,8 @@ public class SystemConfig {
return mDisabledUntilUsedPreinstalledCarrierApps;
}
- public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
+ public ArrayMap<String, List<CarrierAssociatedAppEntry>>
+ getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
}
@@ -954,7 +956,23 @@ public class SystemConfig {
+ "> without package or carrierAppPackage in " + permFile
+ " at " + parser.getPositionDescription());
} else {
- List<String> associatedPkgs =
+ // APKs added to system images via OTA should specify the addedInSdk
+ // attribute, otherwise they may be enabled-by-default in too many
+ // cases. See CarrierAppUtils for more info.
+ int addedInSdk = CarrierAssociatedAppEntry.SDK_UNSPECIFIED;
+ String addedInSdkStr = parser.getAttributeValue(null, "addedInSdk");
+ if (!TextUtils.isEmpty(addedInSdkStr)) {
+ try {
+ addedInSdk = Integer.parseInt(addedInSdkStr);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "<" + name + "> addedInSdk not an integer in "
+ + permFile + " at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ break;
+ }
+ }
+ List<CarrierAssociatedAppEntry> associatedPkgs =
mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
carrierPkgname);
if (associatedPkgs == null) {
@@ -962,7 +980,8 @@ public class SystemConfig {
mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
carrierPkgname, associatedPkgs);
}
- associatedPkgs.add(pkgname);
+ associatedPkgs.add(
+ new CarrierAssociatedAppEntry(pkgname, addedInSdk));
}
} else {
logNotAllowedInPartition(name, permFile, parser);
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 03b9793ccba8..d4805acb06d0 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -226,6 +226,11 @@ static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) {
class_Network, ctor, dnsNetId & ~NETID_USE_LOCAL_NAMESERVERS, privateDnsBypass);
}
+static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jobject thiz,
+ jboolean hasConnectivity) {
+ setAllowNetworkingForProcess(hasConnectivity == JNI_TRUE);
+}
+
static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {
if (javaFd == NULL) {
jniThrowNullPointerException(env, NULL);
@@ -266,6 +271,7 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j
/*
* JNI registration.
*/
+// clang-format off
static const JNINativeMethod gNetworkUtilMethods[] = {
/* name, signature, funcPtr */
{ "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork },
@@ -282,7 +288,9 @@ static const JNINativeMethod gNetworkUtilMethods[] = {
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
{ "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel },
{ "getDnsNetwork", "()Landroid/net/Network;", (void*) android_net_utils_getDnsNetwork },
+ { "setAllowNetworkingForProcess", "(Z)V", (void *)android_net_utils_setAllowNetworkingForProcess },
};
+// clang-format on
int register_android_net_NetworkUtils(JNIEnv* env)
{
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index e553a786da96..ae36f8a7b30b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -395,6 +395,16 @@ static void nativeSetEarlyWakeup(JNIEnv* env, jclass clazz, jlong transactionObj
transaction->setEarlyWakeup();
}
+static void nativeSetEarlyWakeupStart(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setExplicitEarlyWakeupStart();
+}
+
+static void nativeSetEarlyWakeupEnd(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setExplicitEarlyWakeupEnd();
+}
+
static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint zorder) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -1501,6 +1511,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetAnimationTransaction },
{"nativeSetEarlyWakeup", "(J)V",
(void*)nativeSetEarlyWakeup },
+ {"nativeSetEarlyWakeupStart", "(J)V",
+ (void*)nativeSetEarlyWakeupStart },
+ {"nativeSetEarlyWakeupEnd", "(J)V",
+ (void*)nativeSetEarlyWakeupEnd },
{"nativeSetLayer", "(JJI)V",
(void*)nativeSetLayer },
{"nativeSetRelativeLayer", "(JJJI)V",
diff --git a/core/proto/android/stats/connectivity/Android.bp b/core/proto/android/stats/connectivity/Android.bp
index 9cd233e1ba85..5e6ac3cd3ca1 100644
--- a/core/proto/android/stats/connectivity/Android.bp
+++ b/core/proto/android/stats/connectivity/Android.bp
@@ -22,3 +22,17 @@ java_library_static {
],
sdk_version: "system_29",
}
+
+java_library_static {
+ name: "tetheringprotos",
+ proto: {
+ type: "lite",
+ },
+ srcs: [
+ "tethering.proto",
+ ],
+ apex_available: [
+ "com.android.tethering",
+ ],
+ sdk_version: "system_current",
+}
diff --git a/core/proto/android/stats/connectivity/tethering.proto b/core/proto/android/stats/connectivity/tethering.proto
new file mode 100644
index 000000000000..6303b7d1870b
--- /dev/null
+++ b/core/proto/android/stats/connectivity/tethering.proto
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto2";
+package android.stats.connectivity;
+option java_multiple_files = true;
+option java_outer_classname = "TetheringProto";
+
+enum ErrorCode {
+ EC_NO_ERROR = 0;
+ EC_UNKNOWN_IFACE = 1;
+ EC_SERVICE_UNAVAIL = 2;
+ EC_UNSUPPORTED = 3;
+ EC_UNAVAIL_IFACE = 4;
+ EC_INTERNAL_ERROR = 5;
+ EC_TETHER_IFACE_ERROR = 6;
+ EC_UNTETHER_IFACE_ERROR = 7;
+ EC_ENABLE_FORWARDING_ERROR = 8;
+ EC_DISABLE_FORWARDING_ERROR = 9;
+ EC_IFACE_CFG_ERROR = 10;
+ EC_PROVISIONING_FAILED = 11;
+ EC_DHCPSERVER_ERROR = 12;
+ EC_ENTITLEMENT_UNKNOWN = 13;
+ EC_NO_CHANGE_TETHERING_PERMISSION = 14;
+ EC_NO_ACCESS_TETHERING_PERMISSION = 15;
+ EC_UNKNOWN_TYPE = 16;
+}
+
+enum DownstreamType {
+ // Unspecific tethering type.
+ DS_UNSPECIFIED = 0;
+ // Wifi tethering type.
+ DS_TETHERING_WIFI = 1;
+ // USB tethering type.
+ DS_TETHERING_USB = 2;
+ // Bluetooth tethering type.
+ DS_TETHERING_BLUETOOTH = 3;
+ // Wifi P2p tethering type.
+ DS_TETHERING_WIFI_P2P = 4;
+ // NCM (Network Control Model) local tethering type.
+ DS_TETHERING_NCM = 5;
+ // Ethernet tethering type.
+ DS_TETHERING_ETHERNET = 6;
+}
+
+enum UpstreamType {
+ UT_UNKNOWN = 0;
+ // Indicates upstream using a Cellular transport.
+ UT_CELLULAR = 1;
+ // Indicates upstream using a Wi-Fi transport.
+ UT_WIFI = 2;
+ // Indicates upstream using a Bluetooth transport.
+ UT_BLUETOOTH = 3;
+ // Indicates upstream using an Ethernet transport.
+ UT_ETHERNET = 4;
+ // Indicates upstream using a Wi-Fi Aware transport.
+ UT_WIFI_AWARE = 5;
+ // Indicates upstream using a LoWPAN transport.
+ UT_LOWPAN = 6;
+ // Indicates upstream using a Cellular+VPN transport.
+ UT_CELLULAR_VPN = 7;
+ // Indicates upstream using a Wi-Fi+VPN transport.
+ UT_WIFI_VPN = 8;
+ // Indicates upstream using a Bluetooth+VPN transport.
+ UT_BLUETOOTH_VPN = 9;
+ // Indicates upstream using an Ethernet+VPN transport.
+ UT_ETHERNET_VPN = 10;
+ // Indicates upstream using a Wi-Fi+Cellular+VPN transport.
+ UT_WIFI_CELLULAR_VPN = 11;
+ // Indicates upstream using for test only.
+ UT_TEST = 12;
+ // Indicates upstream using DUN capability + Cellular transport.
+ UT_DUN_CELLULAR = 13;
+}
+
+enum UserType {
+ // Unknown.
+ USER_UNKOWNN = 0;
+ // Settings.
+ USER_SETTINGS = 1;
+ // System UI.
+ USER_SYSTEMUI = 2;
+ // Google mobile service.
+ USER_GMS = 3;
+}
diff --git a/core/res/res/drawable-car-night/car_dialog_button_background.xml b/core/res/res/drawable-car-night/car_dialog_button_background.xml
new file mode 100644
index 000000000000..138cb38b0d87
--- /dev/null
+++ b/core/res/res/drawable-car-night/car_dialog_button_background.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true">
+ <ripple android:color="#2371cd">
+ <item android:id="@android:id/mask">
+ <color android:color="@*android:color/car_white_1000"/>
+ </item>
+ </ripple>
+ </item>
+ <item>
+ <ripple android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <color android:color="@*android:color/car_white_1000"/>
+ </item>
+ </ripple>
+ </item>
+</selector>
diff --git a/core/res/res/drawable-car/car_dialog_button_background.xml b/core/res/res/drawable-car/car_dialog_button_background.xml
index 67506cbc12bc..a7d40bcd759a 100644
--- a/core/res/res/drawable-car/car_dialog_button_background.xml
+++ b/core/res/res/drawable-car/car_dialog_button_background.xml
@@ -14,9 +14,19 @@
~ 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="?android:attr/colorControlHighlight">
- <item android:id="@android:id/mask">
- <color android:color="@*android:color/car_white_1000" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true">
+ <ripple android:color="#4b9eff">
+ <item android:id="@android:id/mask">
+ <color android:color="@*android:color/car_white_1000"/>
+ </item>
+ </ripple>
</item>
-</ripple>
+ <item>
+ <ripple android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <color android:color="@*android:color/car_white_1000"/>
+ </item>
+ </ripple>
+ </item>
+</selector>
diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml
index 3188861a52a5..5e3b657353b6 100644
--- a/core/res/res/layout/notification_template_messaging_group.xml
+++ b/core/res/res/layout/notification_template_messaging_group.xml
@@ -37,6 +37,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
+ android:baselineAligned="true"
android:orientation="vertical">
<com.android.internal.widget.ImageFloatingTextView
android:id="@+id/message_name"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 8a68217d966a..89ce3b0eefb9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou foon te ontsluit deur middel van \'n e-posrekening.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwyder"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Die voorgronddiens wat in die agtergrond begin het vanaf <xliff:g id="PACKAGENAME">%1$s</xliff:g> sal nie ingebruik-toestemming hê in toekomstige R-bouweergawes nie. Raadpleeg asseblief go/r-bg-fgs-restriction en dien \'n foutverslag in."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Verhoog volume bo aanbevole vlak?\n\nOm lang tydperke teen hoë volume te luister, kan jou gehoor beskadig."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gebruik toeganklikheidkortpad?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word."</string>
@@ -1651,8 +1650,8 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gebruik kortpad"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kleuromkering"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Kleurkorreksie"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels gehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels gehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> het afgeskakel"</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is afgeskakel"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Druk en hou albei volumesleutels drie sekondes lank om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruik"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Kies \'n kenmerk om te gebruik wanneer jy op die toeganklikheidknoppie tik:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Kies \'n kenmerk om te gebruik saam met die toeganklikheidgebaar (swiep met twee vingers op van die onderkant van die skerm af):"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index a05cfbfc99fd..5eb271e754a6 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"አስወግድ"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"ዳራው ከ<xliff:g id="PACKAGENAME">%1$s</xliff:g> የጀመረው የፊት አገልግሎት ወደፊት በሚኖሩት R ግንቦች ላይ ጥቅም ላይ እየዋለ ፈቃድ አይኖረውም። እባክዎ go/r-bg-fgs-restriction እና ፋይል ሳንካ ሪፖርትን ይመልከቱ።"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ድምጹ ከሚመከረው መጠን በላይ ከፍ ይበል?\n\nበከፍተኛ ድምጽ ለረጅም ጊዜ ማዳመጥ ጆሮዎን ሊጎዳው ይችላል።"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"የተደራሽነት አቋራጭ ጥቅም ላይ ይዋል?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"አቋራጩ ሲበራ ሁለቱንም የድምጽ አዝራሮች ለ3 ሰከንዶች ተጭኖ መቆየት የተደራሽነት ባህሪን ያስጀምረዋል።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 02a0eb476505..f20470f5bcad 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -973,7 +973,7 @@
<string name="permlab_addVoicemail" msgid="4770245808840814471">"إضافة بريد صوتي"</string>
<string name="permdesc_addVoicemail" msgid="5470312139820074324">"للسماح للتطبيق بإضافة رسائل إلى صندوق البريد الصوتي."</string>
<string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"تعديل أذونات الموقع الجغرافي للمتصفح"</string>
- <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"للسماح لأحد التطبيقات بتعديل أذونات الموقع الجغرافي للمتصفح. يمكن أن تستخدم التطبيقات الضارة هذا للسماح بإرسال معلومات الموقع إلى مواقع ويب عشوائية."</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"للسماح لأحد التطبيقات بتعديل أذونات الموقع الجغرافي للمتصفح. يمكن أن تستخدم التطبيقات الضارة هذا للسماح بإرسال معلومات الموقع إلى مواقع إلكترونية عشوائية."</string>
<string name="save_password_message" msgid="2146409467245462965">"هل تريد من المتصفح تذكر كلمة المرور هذه؟"</string>
<string name="save_password_notnow" msgid="2878327088951240061">"ليس الآن"</string>
<string name="save_password_remember" msgid="6490888932657708341">"تذكّر"</string>
@@ -1391,7 +1391,7 @@
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"‏اختيار إيقاف تصحيح أخطاء USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"تم تفعيل ميزة \"تصحيح الأخطاء اللاسلكي\"."</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"انقر لإيقاف ميزة \"تصحيح الأخطاء اللاسلكي\"."</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"اختيار إيقاف ميزة \"تصحيح الأخطاء اللاسلكي\""</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"انقر لإيقاف ميزة \"تصحيح الأخطاء اللاسلكي\""</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"تم تفعيل وضع \"مفعّل الاختبار\""</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"يمكنك إجراء إعادة ضبط على الإعدادات الأصلية لإيقاف وضع \"مفعِّل اختبار\"."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"وحدة التحكّم التسلسلية مفعّلة"</string>
@@ -1707,12 +1707,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"إزالة"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"‏لن يتم منح إذن الوصول إلى الموقع الجغرافي أثناء الاستخدام للخدمات التي تعمل في المقدّمة من <xliff:g id="PACKAGENAME">%1$s</xliff:g> والتي تبدأ من الخلفية في إصدارات R القادمة. يُرجى مراجعة go/r-bg-fgs-restriction وتقديم تقرير خطأ."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"هل تريد رفع مستوى الصوت فوق المستوى الموصى به؟\n\nقد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"هل تريد استخدام اختصار \"سهولة الاستخدام\"؟"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"عند تفعيل الاختصار، يؤدي الضغط على زرّي التحكّم في مستوى الصوت معًا لمدة 3 ثوانٍ إلى تفعيل إحدى ميزات إمكانية الوصول."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"هل تريد تفعيل ميزات إمكانية الوصول؟"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"‏يؤدي الضغط مع الاستمرار على كلا مفتاحَي التحكّم في مستوى الصوت لبضع ثوانٍ إلى تفعيل ميزات إمكانية الوصول. قد يؤدي هذا إلى تغيير كيفية عمل جهازك.\n\nالميزات الحالية:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nيمكنك تغيير الميزات المحددة في الإعدادات &gt; أدوات تمكين الوصول."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"يؤدي الضغط مع الاستمرار على كلا مفتاحَي التحكّم في مستوى الصوت لبضع ثوانٍ إلى تفعيل ميزات إمكانية الوصول. قد يؤدي هذا الإجراء إلى تغيير طريقة عمل جهازك.\n\nالميزات الحالية:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nيمكنك تغيير الميزات المحددة في الإعدادات &gt; إمكانية الوصول."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"هل تريد تفعيل <xliff:g id="SERVICE">%1$s</xliff:g>؟"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"‏يؤدي الضغط مع الاستمرار لبضع ثوانٍ على كلا مفتاحَي التحكّم في مستوى الصوت إلى تفعيل <xliff:g id="SERVICE">%1$s</xliff:g> وهي إحدى ميزات إمكانية الوصول. يمكن أن يؤدي هذا الإجراء إلى تغيير كيفية عمل جهازك.\n\nيمكنك تغيير هذا الاختصار لاستخدامه مع ميزة أخرى في الإعدادات &gt; أدوات تمكين الوصول."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 5ac3aaeb9c6c..f2c7c4551de8 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1619,12 +1619,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"আপুনি আপোনাৰ ল\'ক খোলাৰ আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ আঁকিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল আৰ্হি আঁকিলে আপোনাৰ ফ\'নটো কোনো একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ\'ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"আঁতৰাওক"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"নেপথ্যই <xliff:g id="PACKAGENAME">%1$s</xliff:g>ৰ পৰা আৰম্ভ কৰা অগ্ৰভূমিৰ সেৱাটোৰ ভৱিষ্যতৰ R বিল্ডসমূহত ব্যৱহাৰ হৈ থকা সম্পৰ্কীয় অনুমতি নাথাকিব। অনুগ্ৰহ কৰি go/r-bg-fgs-restriction চাওক আৰু এটা বাগৰিপ\'ৰ্ট ফাইল কৰক।"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"অনুমোদিত স্তৰতকৈ ওপৰলৈ ভলিউম বঢ়াব নেকি?\n\nদীৰ্ঘ সময়ৰ বাবে উচ্চ ভলিউমত শুনাৰ ফলত শ্ৰৱণ ক্ষমতাৰ ক্ষতি হ\'ব পাৰে।"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাট ব্যৱহাৰ কৰেনে?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শ্বৰ্টকাটটো অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটাম ৩ ছেকেণ্ডৰ বাবে হেঁচি ধৰি ৰাখিলে এটা সাধ্য সুবিধা আৰম্ভ হ’ব।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"সাধ্য-সুবিধাসমূহ অন কৰিবনে?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে সাধ্য-সুবিধাসমূহ অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nবর্তমানৰ সুবিধাসমূহ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nআপুনি ছেটিংসমূহ &gt; সাধ্য-সুবিধাত বাছনি কৰা সুবিধাসমূহ সলনি কৰিব পাৰে।"</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে সাধ্য-সুবিধাসমূহ অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nবর্তমানৰ সুবিধাসমূহ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nআপুনি ছেটিংসমূহ &gt; সাধ্য-সুবিধাত কিছুমান নিৰ্দিষ্ট সুবিধা সলনি কৰিব পাৰে।"</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> অন কৰিবনে?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে এটা সাধ্য- সুবিধা <xliff:g id="SERVICE">%1$s</xliff:g> অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nআপুনি ছেটিংসমূহ &gt; সাধ্য-সুবিধাসমূহত এই শ্বৰ্টকাটটো অন্য এটা সুবিধালৈ সলনি কৰিব পাৰে।"</string>
@@ -1652,7 +1651,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"ৰং বিপৰীতকৰণ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ৰং শুধৰণী"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰা হ\'ল।"</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অফ কৰা হ\'ল।"</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধৰি ৰাখিছিল। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অফ কৰা হ\'ল।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যৱহাৰ কৰিবলৈ দুয়োটা ভলিউম বুটাম তিনি ছেকেণ্ডৰ বাবে হেঁচি ৰাখক"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"আপুনি সাধ্য-সুবিধাৰ বুটামটো টিপিলে ব্যৱহাৰ কৰিবলৈ এটা সুবিধা বাছনি কৰক:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"সাধ্য-সুবিধাৰ নির্দেশৰ জৰিয়তে ব্যৱহাৰ কৰিবলৈ এটা সুবিধা বাছনি কৰক (দুটা আঙুলিৰে স্ক্রীনখনৰ একেবাৰে তলিৰ পৰা ওপৰলৈ ছোৱাইপ কৰক):"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 106f7040c1a4..2c75c866f1c0 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Siz artıq modeli <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etmisiniz.<xliff:g id="NUMBER_1">%2$d</xliff:g> dəfə də yanlış daxil etsəniz, telefonun kilidinin açılması üçün elektron poçt ünvanınız tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə ərzində yenidən cəhd edin."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Yığışdır"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Arxa fonda başladılan <xliff:g id="PACKAGENAME">%1$s</xliff:g> üzrə ön plan xidmətinin gələcək R versiyalarında \"istifadə zamanı\" icazəsi olmayacaq. go/r-bg-fgs-restriction bölməsinə keçin və baq hesabatı göndərin."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Səsin həcmi tövsiyə olunan səviyyədən artıq olsun?\n\nYüksək səsi uzun zaman dinləmək eşitmə qabiliyyətinizə zərər vura bilər."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Əlçatımlılıq Qısayolu istifadə edilsin?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Qısayol aktiv olduqda, hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası başladılacaq."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 56e7a2703d5e..7fb53f6e269b 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1641,7 +1641,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde/i."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Usluga u prvom planu sa <xliff:g id="PACKAGENAME">%1$s</xliff:g> koja je pokrenuta u pozadini neće imati dozvolu tokom korišćenja u budućim R verzijama. Posetite go/r-bg-fgs-restriction i pošaljite izveštaj o grešci."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li da koristite prečicu za pristupačnost?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 84136225de38..57e6409c93c0 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1663,7 +1663,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькiх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакiраваць тэлефон, увайшоўшы ў Google.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Выдалiць"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Запушчаны ў фонавым рэжыме асноўны сэрвіс з пакета \"<xliff:g id="PACKAGENAME">%1$s</xliff:g>\" не будзе мець дазволу while-in-use у будучых зборках на мове R. Наведайце сайт go/r-bg-fgs-restriction і адпраўце справаздачу пра памылку."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Павялiчыць гук вышэй рэкамендаванага ўзроўню?\n\nДоўгае праслухоўванне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Выкарыстоўваць камбінацыю хуткага доступу для спецыяльных магчымасцей?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Калі хуткі доступ уключаны, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб запусціць функцыю спецыяльных магчымасцей."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index a574fec312b6..60931a6f22e3 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1619,11 +1619,10 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Премахване"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Задният план, който е стартирал услуга на преден план от <xliff:g id="PACKAGENAME">%1$s</xliff:g>, няма да има разрешение при използване в бъдещите компилации R. Моля, вижте go/r-bg-fgs-restriction и подайте сигнал за програмна грешка."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да се увеличи ли силата на звука над препоръчителното ниво?\n\nПродължителното слушане при висока сила на звука може да увреди слуха ви."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Искате ли да използвате пряк път към функцията за достъпност?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Когато прекият път е включен, можете да стартирате дадена функция за достъпност, като натиснете двата бутона за силата на звука и ги задържите за 3 секунди."</string>
- <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Да се включат ли функциите за достъпност?"</string>
+ <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Включване на функциите за достъпност?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Натиснете двата бутона за силата на звука и ги задръжте за няколко секунди, за да включите функциите за достъпност. Това може да промени начина, по който работи устройството ви.\n\nТекущи функции:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nМожете да промените избраните функции от „Настройки“ &gt; „Достъпност“."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Да се включи ли <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 98c778cbd759..d560ce934440 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -238,7 +238,7 @@
<string name="global_action_lock" msgid="6949357274257655383">"স্ক্রীণ লক"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"পাওয়ার বন্ধ করুন"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"ফোন বন্ধ করুন"</string>
- <string name="global_action_restart" msgid="4678451019561687074">"ফোন আবার চালু করুন"</string>
+ <string name="global_action_restart" msgid="4678451019561687074">"ফোন রিস্টার্ট করুন"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"জরুরী"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"ত্রুটির প্রতিবেদন"</string>
<string name="global_action_logout" msgid="6093581310002476511">"সেশন শেষ করুন"</string>
@@ -1619,12 +1619,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ আর <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টা করা হলে আপনাকে একটি ইমেল অ্যাকাউন্ট মারফত আপনার ফোন আনলক করতে বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"সরান"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> থেকে শুরু হওয়া ফোরগ্রাউন্ড পরিষেবাটির ভবিষ্যতে আর বিল্ডগুলিতে ব্যবহারের অনুমতি নেই। go/r-bg-fgs-restriction দেখুন এবং বাগরিপোর্ট জমা দিন।"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"প্রস্তাবিত স্তরের চেয়ে বেশি উঁচুতে ভলিউম বাড়াবেন?\n\nউঁচু ভলিউমে বেশি সময় ধরে কিছু শুনলে আপনার শ্রবনশক্তির ক্ষতি হতে পারে।"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"অ্যাক্সেসযোগ্যতা শর্টকাট ব্যবহার করবেন?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শর্টকাট চালু করা থাকাকালীন দুটি ভলিউম বোতাম একসাথে ৩ সেকেন্ড টিপে ধরে রাখলে একটি অ্যাকসেসিবিলিটি ফিচার চালু হবে।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"অ্যাক্সেসিবিলিটি ফিচার চালু করতে চান?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"উভয় ভলিউম কী কয়েক সেকেন্ড ধরে থাকলে অ্যাক্সেসিবিলিটি ফিচার চালু হয়ে যাবে। এর ফলে, আপনার ডিভাইস কীভাবে কাজ করবে সেটিতে পরিবর্তন হতে পারে।\n\nবর্তমান ফিচার:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nসেটিংস &gt; অ্যাক্সেসিবিলিটি থেকে আপনি বাছাই করা ফিচার পরিবর্তন করতে পারবেন।"</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"উভয় ভলিউম কী কয়েক সেকেন্ড ধরে থাকলে অ্যাক্সেসিবিলিটি ফিচার চালু হয়ে যাবে। এর ফলে, আপনার ডিভাইস কীভাবে কাজ করবে সেটিতে পরিবর্তন হতে পারে।\n\nবর্তমান ফিচার:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nসেটিংস &gt; অ্যাক্সেসিবিলিটি বিকল্প থেকে আপনি বাছাই করা ফিচার পরিবর্তন করতে পারবেন।"</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> চালু করতে চান?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"উভয় ভলিউম কী কয়েক সেকেন্ড ধরে থাকলে <xliff:g id="SERVICE">%1$s</xliff:g> চালু হয়ে যাবে। এটি একটি অ্যাক্সেসিবিলিটি ফিচার। এর ফলে, আপনার ডিভাইস কীভাবে কাজ করবে সেটিতে পরিবর্তন হতে পারে।\n\nসেটিংস &gt; অ্যাক্সেসিবিলিটি থেকে আপনি এই শর্টকাট পরিবর্তন করতে পারবেন।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 8c0459103696..5da4183eb6d7 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1328,7 +1328,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Priključeni uređaj nije kompatibilan s ovim telefonom. Dodirnite da saznate više."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Otklanjanje grešaka putem USB-a je uspostavljeno"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Dodirnite da isključite otklanjanje grešaka putem USB-a"</string>
- <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Odaberite da onemogućite ispravljanje grešaka koristeći USB"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Odaberite da onemogućite otklanjanje grešaka putem USB-a"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Bežično otklanjanje grešaka je povezano"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Dodirnite da isključite bežično otklanjanje grešaka"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Odaberite da onemogućite bežično otklanjanje grešaka."</string>
@@ -1641,7 +1641,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako napravite još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate telefon pomoću e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Usluge iz prvog plana započete u pozadini s web lokacije <xliff:g id="PACKAGENAME">%1$s</xliff:g> neće imati odobrenje za funkciju \"za vrijeme korištenja\" u budućim R verzijama. Pogledajte go/r-bg-fgs-restriction i podnesite izvještaj o greškama."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučenog nivoa?\n\nDužim slušanjem glasnog zvuka možete oštetiti sluh."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li koristiti Prečicu za pristupačnost?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritiskom i držanjem oba dugmeta za jačinu zvuka u trajanju od 3 sekunde pokrenut će se funkcija pristupačnosti."</string>
@@ -1651,7 +1650,7 @@
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Uključiti <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ako nekoliko sekundi držite pritisnute obje tipke za jačinu zvuka, uključit ćete funkciju pristupačnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Ovo može promijeniti način rada uređaja.\n\nOvu prečicu možete zamijeniti drugom funkcijom u odjeljku Postavke &gt; Pristupačnost."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Uključi"</string>
- <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Nemoj uključivati"</string>
+ <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Nemoj uključiti"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"UKLJUČENO"</string>
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"ISKLJUČENO"</string>
<string name="accessibility_enable_service_title" msgid="3931558336268541484">"Dozvoliti da usluga <xliff:g id="SERVICE">%1$s</xliff:g> ima punu kontrolu nad vašim uređajem?"</string>
@@ -1665,7 +1664,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Odbij"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite funkciju da je počnete koristiti:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odaberite funkcije koje ćete koristiti s dugmetom Pristupačnost"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odaberite funkcije koje ćete koristiti s tipkom prečice za jačinu zvuka"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odaberite funkcije koje ćete koristiti pomoću prečice tipke za jačinu zvuka"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečice"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
@@ -1953,7 +1952,7 @@
<string name="app_category_maps" msgid="6395725487922533156">"Mape i navigacija"</string>
<string name="app_category_productivity" msgid="1844422703029557883">"Produktivnost"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Memorija uređaja"</string>
- <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"Otklanjanje grešaka putem uređaja spojenog na USB"</string>
+ <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"Otklanjanje grešaka putem USB-a"</string>
<string name="time_picker_hour_label" msgid="4208590187662336864">"sat"</string>
<string name="time_picker_minute_label" msgid="8307452311269824553">"minuta"</string>
<string name="time_picker_header_text" msgid="9073802285051516688">"Postavljanje vremena"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index fc9471f5d449..0a5907ef4274 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -237,7 +237,7 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Opcions del telèfon"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Bloqueig de pantalla"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Apaga"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Engegada"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Engega"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Reinicia"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Emergència"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Informe d\'error"</string>
@@ -264,7 +264,7 @@
<string name="global_action_settings" msgid="4671878836947494217">"Configuració"</string>
<string name="global_action_assist" msgid="2517047220311505805">"Assistència"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"Assist. per veu"</string>
- <string name="global_action_lockdown" msgid="2475471405907902963">"Bloq. de seguretat"</string>
+ <string name="global_action_lockdown" msgid="2475471405907902963">"Bloqueig de seguretat"</string>
<string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"+999"</string>
<string name="notification_hidden_text" msgid="2835519769868187223">"Notificació nova"</string>
<string name="notification_channel_virtual_keyboard" msgid="6465975799223304567">"Teclat virtual"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Elimina"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"El servei en primer pla (<xliff:g id="PACKAGENAME">%1$s</xliff:g>) iniciat en segon pla no tindrà permís durant l\'ús en compilacions R posteriors. Consulta la pàgina go/r-bg-fgs-restriction i presenta un informe d\'errors."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vols apujar el volum per sobre del nivell recomanat?\n\nSi escoltes música a un volum alt durant períodes llargs, pots danyar-te l\'oïda."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vols fer servir la drecera d\'accessibilitat?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Si la drecera està activada, prem els dos botons de volum durant 3 segons per iniciar una funció d\'accessibilitat."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 90ee8f25d2bf..3b7a6edb4783 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1663,7 +1663,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odebrat"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Služba v popředí z balíčku <xliff:g id="PACKAGENAME">%1$s</xliff:g>, která byla spuštěna na pozadí, v budoucích sestavenách typu R nebude mít oprávnění ke spuštění při používání. Přejděte na adresu go/r-bg-fgs-restriction a vyplňte zprávu o chybě."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšit hlasitost nad doporučenou úroveň?\n\nDlouhodobý poslech hlasitého zvuku může poškodit sluch."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použít zkratku přístupnosti?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Když je tato zkratka zapnutá, můžete funkci přístupnosti spustit tím, že na tři sekundy podržíte obě tlačítka hlasitosti."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 16cae27eb2fa..bd5a0d37dd85 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -264,7 +264,7 @@
<string name="global_action_settings" msgid="4671878836947494217">"Indstillinger"</string>
<string name="global_action_assist" msgid="2517047220311505805">"Assistance"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"Taleassistent"</string>
- <string name="global_action_lockdown" msgid="2475471405907902963">"Lukning"</string>
+ <string name="global_action_lockdown" msgid="2475471405907902963">"Lås enhed"</string>
<string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999+"</string>
<string name="notification_hidden_text" msgid="2835519769868187223">"Ny notifikation"</string>
<string name="notification_channel_virtual_keyboard" msgid="6465975799223304567">"Virtuelt tastatur"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Tjenesten i forgrunden fra <xliff:g id="PACKAGENAME">%1$s</xliff:g>, der starter i baggrunden, vil i fremtidige R-builds ikke have tilladelse, mens den er i brug. Se go/r-bg-fgs-restriction, og indsend en fejlrapport."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget høj musik over længere tid."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruge genvejen til Hjælpefunktioner?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når genvejen er aktiveret, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Afvis"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryk på en funktion for at bruge den:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Vælg, hvilke funktioner du vil bruge med knappen Hjælpefunktioner"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Vælg, hvilke funktioner du vil bruge med genvejen via lydstyrkeknapperne"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Vælg de funktioner, du vil bruge via lydstyrkeknapperne"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> er blevet deaktiveret"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediger genveje"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Udfør"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 2763acad2672..a2a4adc782c2 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Telefon mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden erneut."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Entfernen"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Der Dienst im Vordergrund von <xliff:g id="PACKAGENAME">%1$s</xliff:g>, der im Hintergrund gestartet wurde, hat in zukünftigen R-Builds keine Zugriffsberechtigung mehr während der Nutzung. Siehe dazu go/r-bg-fgs-restriction und reiche einen Fehlerbericht ein."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lautstärke über den Schwellenwert anheben?\n\nWenn du über einen längeren Zeitraum Musik in hoher Lautstärke hörst, kann dies dein Gehör schädigen."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Verknüpfung für Bedienungshilfen verwenden?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wenn die Verknüpfung aktiviert ist, kannst du die beiden Lautstärketasten drei Sekunden lang gedrückt halten, um eine Bedienungshilfe zu starten."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Ablehnen"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Zum Auswählen der gewünschten Funktion tippen:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Funktionen auswählen, die du mit der Schaltfläche \"Bedienungshilfen\" verwenden möchtest"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Funktionen auswählen, die du mit der Verknüpfung für die Lautstärketaste verwenden möchtest"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Funktionen für Verknüpfung mit Lautstärketaste auswählen"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> wurde deaktiviert"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Verknüpfungen bearbeiten"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fertig"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index dd19b2769f72..916ad5f1ac21 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Κατάργηση"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Η υπηρεσία στο προσκήνιο που ξεκίνησε από το παρασκήνιο από το πακέτο <xliff:g id="PACKAGENAME">%1$s</xliff:g> δεν θα έχει άδεια πρόσβασης μόνο κατά τη χρήση σε μελλοντικές εκδόσεις R. Ανατρέξτε στο go/r-bg-fgs-restriction και υποβάλετε αναφορά σφάλματος."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Αυξάνετε την ένταση ήχου πάνω από το επίπεδο ασφαλείας;\n\nΑν ακούτε μουσική σε υψηλή ένταση για μεγάλο χρονικό διάστημα ενδέχεται να προκληθεί βλάβη στην ακοή σας."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Να χρησιμοποιείται η συντόμευση προσβασιμότητας;"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Όταν η συντόμευση είναι ενεργοποιημένη, το πάτημα και των δύο κουμπιών έντασης ήχου για 3 δευτερόλεπτα θα ξεκινήσει μια λειτουργία προσβασιμότητας."</string>
@@ -1652,7 +1651,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"Αντιστροφή χρωμάτων"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Διόρθωση χρωμάτων"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ενεργοποιήθηκε."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> απενεργοποιήθηκε."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>: απενεργοποιημένο"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Πατήστε παρατεταμένα και τα δύο κουμπιά έντασης ήχου για τρία δευτερόλεπτα, ώστε να χρησιμοποιήσετε την υπηρεσία <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Επιλέξτε μια λειτουργία που θα χρησιμοποιείται κατά το πάτημα του κουμπιού προσβασιμότητας:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Επιλέξτε μια λειτουργία που θα χρησιμοποιείται με την κίνηση προσβασιμότητας (σύρετε με δύο δάχτυλα προς τα επάνω από το κάτω μέρος της οθόνης):"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 359052488f52..779fdff59351 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"The background started foreground service from <xliff:g id="PACKAGENAME">%1$s</xliff:g> will not have while-in-use permission in future R builds. Please see go/r-bg-fgs-restriction and file a bug report."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
@@ -1650,7 +1649,7 @@
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
- <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour Correction"</string>
+ <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1766,7 +1765,7 @@
<string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Confirm new PIN"</string>
<string name="restr_pin_create_pin" msgid="917067613896366033">"Create a PIN for modifying restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PINs don\'t match. Try again."</string>
- <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least 4 digits."</string>
+ <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least four digits."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
<item quantity="other">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
<item quantity="one">Try again in 1 second</item>
@@ -1793,8 +1792,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”\n\n"<annotation id="url">"Learn more"</annotation></string>
- <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'\n\n"<annotation id="url">"Learn more"</annotation></string>
+ <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'"</string>
<string name="data_saver_description" msgid="4995164271550590517">"To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app that you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Turn on Data Saver?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Turn on"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index baf246cad231..2ec280585ad1 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"The background started foreground service from <xliff:g id="PACKAGENAME">%1$s</xliff:g> will not have while-in-use permission in future R builds. Please see go/r-bg-fgs-restriction and file a bug report."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
@@ -1650,7 +1649,7 @@
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
- <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour Correction"</string>
+ <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1766,7 +1765,7 @@
<string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Confirm new PIN"</string>
<string name="restr_pin_create_pin" msgid="917067613896366033">"Create a PIN for modifying restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PINs don\'t match. Try again."</string>
- <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least 4 digits."</string>
+ <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least four digits."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
<item quantity="other">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
<item quantity="one">Try again in 1 second</item>
@@ -1793,8 +1792,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”\n\n"<annotation id="url">"Learn more"</annotation></string>
- <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'\n\n"<annotation id="url">"Learn more"</annotation></string>
+ <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'"</string>
<string name="data_saver_description" msgid="4995164271550590517">"To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app that you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Turn on Data Saver?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Turn on"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 359052488f52..779fdff59351 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"The background started foreground service from <xliff:g id="PACKAGENAME">%1$s</xliff:g> will not have while-in-use permission in future R builds. Please see go/r-bg-fgs-restriction and file a bug report."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
@@ -1650,7 +1649,7 @@
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
- <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour Correction"</string>
+ <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1766,7 +1765,7 @@
<string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Confirm new PIN"</string>
<string name="restr_pin_create_pin" msgid="917067613896366033">"Create a PIN for modifying restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PINs don\'t match. Try again."</string>
- <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least 4 digits."</string>
+ <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least four digits."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
<item quantity="other">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
<item quantity="one">Try again in 1 second</item>
@@ -1793,8 +1792,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”\n\n"<annotation id="url">"Learn more"</annotation></string>
- <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'\n\n"<annotation id="url">"Learn more"</annotation></string>
+ <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'"</string>
<string name="data_saver_description" msgid="4995164271550590517">"To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app that you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Turn on Data Saver?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Turn on"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 359052488f52..779fdff59351 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"The background started foreground service from <xliff:g id="PACKAGENAME">%1$s</xliff:g> will not have while-in-use permission in future R builds. Please see go/r-bg-fgs-restriction and file a bug report."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
@@ -1650,7 +1649,7 @@
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
- <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour Correction"</string>
+ <string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1766,7 +1765,7 @@
<string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Confirm new PIN"</string>
<string name="restr_pin_create_pin" msgid="917067613896366033">"Create a PIN for modifying restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PINs don\'t match. Try again."</string>
- <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least 4 digits."</string>
+ <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN is too short. Must be at least four digits."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
<item quantity="other">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
<item quantity="one">Try again in 1 second</item>
@@ -1793,8 +1792,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”\n\n"<annotation id="url">"Learn more"</annotation></string>
- <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like “Hey Google”"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'\n\n"<annotation id="url">"Learn more"</annotation></string>
+ <string name="battery_saver_description" msgid="8587408568232177204">"To extend battery life, Battery Saver:\n\n•Turns on Dark theme\n•Turns off or restricts background activity, some visual effects and other features like \'Hey Google\'"</string>
<string name="data_saver_description" msgid="4995164271550590517">"To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app that you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Turn on Data Saver?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Turn on"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 31abd8235bf4..fef02fbc3daa 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your phone using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎ — ‎‏‎‎‏‎ "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎Remove‎‏‎‎‏‎"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎The background started foreground service from ‎‏‎‎‏‏‎<xliff:g id="PACKAGENAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ will not have while-in-use permission in future R builds. Please see go/r-bg-fgs-restriction and file a bugreport.‎‏‎‎‏‎"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎Raise volume above recommended level?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Listening at high volume for long periods may damage your hearing.‎‏‎‎‏‎"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎Use Accessibility Shortcut?‎‏‎‎‏‎"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 005dd5d5f6de..35f3766e0c19 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu dispositivo mediante el uso de una cuenta de correo.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminar"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"El servicio que pasó del segundo al primer plano de <xliff:g id="PACKAGENAME">%1$s</xliff:g> no tendrá permiso durante el uso en las próximas compilaciones de R. Ve a go/r-bg-fgs-restriction y envía un informe de errores."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar a un alto volumen durante largos períodos puede dañar tu audición."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Usar acceso directo de accesibilidad?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cuando la combinación de teclas está activada, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Rechazar"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Presiona una función para comenzar a usarla:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Selecciona las funciones a utilizar con el botón de accesibilidad"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona las funciones a utilizar con la combinación de teclas de volumen"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona las funciones a usar con las teclas de volumen"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Se desactivó <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Listo"</string>
@@ -1651,7 +1650,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar acceso directo"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de color"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Al mantener presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Como mantuviste presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Al mantener presionadas las teclas de volumen, se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén presionadas ambas teclas de volumen durante tres segundos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Elige una función para usar cuando pulses el botón accesibilidad:"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8e182a24c7e3..4640e4b699d6 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, deberás usar una cuenta de correo electrónico para desbloquear el teléfono.\n\n Inténtalo de nuevo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Quitar"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"El servicio en primer plano que se inició en segundo plano en <xliff:g id="PACKAGENAME">%1$s</xliff:g> no tendrá permisos en compilaciones R futuras mientras se estén usando. Ve a go/r-bg-fgs-restriction y envía un informe de errores."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar sonidos fuertes durante mucho tiempo puede dañar los oídos."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Utilizar acceso directo de accesibilidad?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Si el acceso directo está activado, pulsa los dos botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index e7239eb46e41..6b5741cb6913 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eemalda"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Taustal käitatud esiplaanil oleval teenusel paketist <xliff:g id="PACKAGENAME">%1$s</xliff:g> ei ole tulevastes R-järkudes luba „kui kasutuses”. Vaadake saiti go/r-bg-fgs-restriction ja esitage veaaruanne."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Kas suurendada helitugevuse taset üle soovitatud taseme?\n\nPikaajaline valju helitugevusega kuulamine võib kuulmist kahjustada."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Kas kasutada juurdepääsetavuse otseteed?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kui otsetee on sisse lülitatud, käivitab mõlema helitugevuse nupu kolm sekundit all hoidmine juurdepääsetavuse funktsiooni."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 9f927c3015d5..e4fe179e89a7 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -512,7 +512,7 @@
<string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"Telefonoa WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_bluetooth" msgid="586333280736937209">"partekatu Bluetooth bidezko gailuekin"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tabletaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string>
- <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV gailuaren Bluetooth konexioaren konfigurazioa ikusteko eta parekatutako gailuekin konexioak sortzeko eta onartzeko baimena ematen die aplikazioei."</string>
+ <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV gailuaren Bluetooth bidezko konexioaren konfigurazioa ikusteko eta parekatutako gailuekin konexioak sortzeko eta onartzeko baimena ematen die aplikazioei."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Telefonoaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Aplikazioari baimena ematen dio NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa jasotzeko, hala nola erregistratutako laguntzaileak eta ibilbidearen helmuga."</string>
@@ -1309,9 +1309,9 @@
<string name="adb_active_notification_title" msgid="408390247354560331">"USB bidezko arazketa konektatuta"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Sakatu USB bidezko arazketa desaktibatzeko"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Hautatu USB bidezko arazketa desgaitzeko."</string>
- <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Konektatu da hari gabeko arazketa"</string>
+ <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Hari gabeko arazketa konektatuta dago"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Sakatu hau hari gabeko arazketa desaktibatzeko"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Hautatu hau hari gabeko arazketa desgaitzeko"</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Hautatu hau hari gabeko arazketa desgaitzeko."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Proba-materialeko modua gaitu da"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Proba-materialaren modua desgaitzeko, berrezarri jatorrizko datuak."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Serie-kontsola gaituta"</string>
@@ -1619,15 +1619,14 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kendu"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> webgunearen atzeko planoak hasitako aurreko planoko zerbitzuak ez du izango erabili bitarteko baimenik etorkizuneko R konpilazioetan. Joan go/r-bg-fgs-restriction atalera eta egin akatsaren txostena."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bolumena gomendatutako mailatik gora igo nahi duzu?\n\nMusika bolumen handian eta denbora luzez entzuteak entzumena kalte diezazuke."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erabilerraztasun-lasterbidea erabili nahi duzu?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Erabilerraztasun-eginbideak aktibatu nahi dituzu?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-teklak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Honen bidez, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nUneko eginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAukeratutako eginbideak aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-botoiak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Hori eginez gero, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nUneko eginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nHautatutako eginbideak aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> aktibatu nahi duzu?"</string>
- <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Eduki sakatuta bolumen-teklak segundo batzuez <xliff:g id="SERVICE">%1$s</xliff:g> izeneko erabilerraztasun-eginbidea aktibatzeko. Honen bidez, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nLasterbide hau beste eginbide batengatik aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
+ <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Eduki sakatuta bolumen-botoiak segundo batzuez <xliff:g id="SERVICE">%1$s</xliff:g> izeneko erabilerraztasun-eginbidea aktibatzeko. Honen bidez, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nLasterbide hau beste eginbide batengatik aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktibatu"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"Ez aktibatu"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"AKTIBATUTA"</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Ukatu"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Eginbide bat erabiltzen hasteko, saka ezazu:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Aukeratu zein eginbide erabili nahi duzun Erabilerraztasuna botoiarekin"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Aukeratu zein eginbide erabili nahi duzun bolumen-teklen lasterbidearekin"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Aukeratu zein eginbide erabili nahi duzun bolumen-botoien lasterbidearekin"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Desaktibatu da <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editatu lasterbideak"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Eginda"</string>
@@ -1651,9 +1650,9 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Erabili lasterbidea"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Koloreen alderantzikatzea"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Koloreen zuzenketa"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Eduki sakatuta bolumen-teklak. Aktibatu da <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Eduki sakatuta bolumen-teklak. Desaktibatu da <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
- <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> erabiltzeko, eduki sakatuta bolumen-tekla biak hiru segundoz"</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu egin da."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu egin da."</string>
+ <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> erabiltzeko, eduki sakatuta bi bolumen-botoiak hiru segundoz"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Aukeratu zein eginbide erabili nahi duzun Erabilerraztasuna botoia sakatzean:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Aukeratu zein eginbide erabili nahi duzun erabilerraztasun-keinuarekin (hau da, bi hatz pantailaren behealdetik gora pasatzean):"</string>
<string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Aukeratu zein eginbide erabili nahi duzun erabilerraztasun-keinuarekin (hau da, hiru hatz pantailaren behealdetik gora pasatzean):"</string>
@@ -2024,7 +2023,7 @@
<string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> kalkulu-orria"</string>
<string name="mime_type_presentation" msgid="1145384236788242075">"Aurkezpena"</string>
<string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> aurkezpena"</string>
- <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth konexioak aktibatuta jarraituko du hegaldi moduan"</string>
+ <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth-ak aktibatuta jarraituko du hegaldi moduan"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"Kargatzen"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fitxategi</item>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2287160a70d2..2cd3dbda1d5f 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"‏شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل تلفن خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"حذف"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"‏سرویس پیش‌نمای <xliff:g id="PACKAGENAME">%1$s</xliff:g>، که در پس‌زمینه شروع شده، در ساخت‌های آتی R اجازهٔ حین استفاده نخواهد داشت. لطفاً به go/r-bg-fgs-restriction بروید و گزارش اشکال ارسال کنید."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"میزان صدا را به بالاتر از حد توصیه شده افزایش می‌دهید؟\n\nگوش دادن به صداهای بلند برای مدت طولانی می‌تواند به شنوایی‌تان آسیب وارد کند."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"از میان‌بر دسترس‌پذیری استفاده شود؟"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"وقتی میان‌بر روشن باشد، با فشار دادن هردو دکمه صدا به‌مدت ۳ ثانیه ویژگی دسترس‌پذیری فعال می‌شود."</string>
@@ -1628,7 +1627,7 @@
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> روشن شود؟"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"با پایین نگه داشتن هردو کلید میزان صدا به‌مدت چند ثانیه، <xliff:g id="SERVICE">%1$s</xliff:g> (یکی از ویژگی‌های دسترس‌پذیری) روشن می‌شود. با این کار نحوه عملکرد دستگاهتان تغییر می‌کند.\n\nمی‌توانید در «تنظیمات &gt; دسترس‌پذیری»،‌این میان‌بر را به ویژگی دیگری تغییر دهید."</string>
- <string name="accessibility_shortcut_on" msgid="5463618449556111344">"روشن کردن"</string>
+ <string name="accessibility_shortcut_on" msgid="5463618449556111344">"روشن شود"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"روشن نشود"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"روشن"</string>
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"خاموش"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index f0ce863c5bb8..6aab2c3cc0b6 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -238,7 +238,7 @@
<string name="global_action_lock" msgid="6949357274257655383">"Näytön lukitus"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Katkaise virta"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Virta"</string>
- <string name="global_action_restart" msgid="4678451019561687074">"Uudelleenkäynnistys"</string>
+ <string name="global_action_restart" msgid="4678451019561687074">"Käynnistä uudelleen"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Hätäpuhelu"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Virheraportti"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Lopeta käyttökerta"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään poistamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Poista"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Taustalla aloitettu etualan palvelu (<xliff:g id="PACKAGENAME">%1$s</xliff:g>) ei ole käytön aikana sallittu R:n tulevissa versioissa. Lue go/r-bg-fgs-restriction ja lähetä virheraportti."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Nostetaanko äänenvoimakkuus suositellun tason yläpuolelle?\n\nPitkäkestoinen kova äänenvoimakkuus saattaa heikentää kuuloa."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Käytetäänkö esteettömyyden pikanäppäintä?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kun pikanäppäin on käytössä, voit käynnistää esteettömyystoiminnon pitämällä molempia äänenvoimakkuuspainikkeita painettuna kolmen sekunnin ajan."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 2eba43f5ae7a..70f403c56ed3 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Le service de premier plan qui a démarré en arrière-plan provenant de <xliff:g id="PACKAGENAME">%1$s</xliff:g> ne disposera pas de l\'autorisation pendant l\'utilisation dans les futures versions R. Veuillez accéder à go/r-bg-fgs-restriction et envoyer un rapport de bogue."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au-dessus du niveau recommandé?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 151f13d5176b..0b3a6af36f8d 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Le service de premier plan qui a démarré en arrière-plan et provenant de <xliff:g id="PACKAGENAME">%1$s</xliff:g> ne disposera pas de l\'autorisation \"pendant l\'utilisation\" dans les futurs builds R. Veuillez accéder à go/r-bg-fgs-restriction et envoyer un rapport de bug."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au dessus du niveau recommandé ?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité ?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour démarrer une fonctionnalité d\'accessibilité."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 8272fed8cc97..77a1fec768d7 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Debuxaches o padrón de desbloqueo incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminar"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Nas futuras compilacións R, o servizo en primeiro plano iniciado en segundo plano desde <xliff:g id="PACKAGENAME">%1$s</xliff:g> non terá permiso mentres estea en uso. Consulta go/r-bg-fgs-restriction e presenta un informe de erros."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Queres subir o volume máis do nivel recomendado?\n\nA reprodución de son a un volume elevado durante moito tempo pode provocar danos nos oídos."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Queres utilizar o atallo de accesibilidade?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cando o atallo está activado, podes premer os dous botóns de volume durante 3 segundos para iniciar unha función de accesibilidade."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Denegar"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocar unha función para comezar a utilizala:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escoller as funcións que queres utilizar co botón Accesibilidade"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escoller as funcións que queres utilizar co atallo da tecla de volume"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolle as funcións que queres utilizar co atallo da tecla de volume"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>: desactivouse"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atallos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Feito"</string>
@@ -1651,8 +1650,8 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atallo"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de cor"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de cor"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activado."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desactivado."</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Activouse o servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Desactivouse <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premidas as teclas do volume durante tres segudos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolle a función que queres utilizar cando toques o botón Accesibilidade:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolle a función que queres usar co xesto de accesibilidade (pasa dous dedos cara arriba desde a parte inferior da pantalla):"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index a2317e9e1cad..f445883a801b 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી. હજી <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસ પછી, તમને ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને ફોનને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"દૂર કરો"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"બૅકગ્રાઉન્ડમાં શરૂ થયેલી <xliff:g id="PACKAGENAME">%1$s</xliff:g>ની ફોરગ્રાઉન્ડ સેવા પાસે ભવિષ્યની R બિલ્ડમાં ઉપયોગમાં હોય તે સમયની પરવાનગી હશે નહીં. કૃપા કરીને go/r-bg-fgs-restriction જુઓ અને ભૂલનો અહેવાલ દાખલ કરો."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ભલામણ કરેલ સ્તરની ઉપર વૉલ્યૂમ વધાર્યો?\n\nલાંબા સમય સુધી ઊંચા અવાજે સાંભળવું તમારી શ્રવણક્ષમતાને નુકસાન પહોંચાડી શકે છે."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ઍક્સેસિબિલિટી શૉર્ટકટનો ઉપયોગ કરીએ?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 9f618d5accbd..9b47f8090e89 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से प्रयास करें."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"निकालें"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g>से बैकग्राउंड में शुरू की गई फ़ॉरग्राउंड सेवा के लिए, भविष्य के R बिल्ड में \'इस्तेमाल के समय अनुमति दें\' की सुविधा नहीं होगी. कृपया go/r-bg-fgs-restriction देखें और गड़बड़ी की शिकायत करें."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"वॉल्यूम को सुझाए गए स्तर से ऊपर बढ़ाएं?\n\nअत्यधिक वॉल्यूम पर ज़्यादा समय तक सुनने से आपकी सुनने की क्षमता को नुकसान हो सकता है."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"सुलभता शॉर्टकट का इस्तेमाल करना चाहते हैं?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट के चालू होने पर, दाेनाें वॉल्यूम बटन (आवाज़ कम या ज़्यादा करने वाले बटन) को तीन सेकंड तक दबाने से, सुलभता सुविधा शुरू हाे जाएगी."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 17f40f15bbe3..5076aa94b1ea 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -239,7 +239,7 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Opcije telefona"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Zaključavanje zaslona"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Isključi"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Napajanje"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Uključi"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Ponovo pokreni"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Hitne službe"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Izvješće o bugovima"</string>
@@ -1641,7 +1641,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g> morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Usluga u prednjem planu s <xliff:g id="PACKAGENAME">%1$s</xliff:g> pokrenuta u pozadini neće imati dopuštenje tijekom upotrebe u budućim R kompilacijama. Pogledajte go/r-bg-fgs-restriction i pošaljite izvješće o programskoj pogrešci."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučene razine?\n\nDugotrajno slušanje glasne glazbe može vam oštetiti sluh."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li upotrebljavati prečac za pristupačnost?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad je taj prečac uključen, pritiskom na obje tipke za glasnoću na tri sekunde pokrenut će se značajka pristupačnosti."</string>
@@ -1667,7 +1666,7 @@
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odabir značajki za upotrebu pomoću gumba za Pristupačnost"</string>
<string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odabir značajki za upotrebu pomoću prečaca tipki za glasnoću"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
- <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečace"</string>
+ <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredite prečace"</string>
<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>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 302dc6925085..6b442137da18 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a telefonját.\n\n Kérjük, próbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eltávolítás"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"A háttér által indított előtérben futó szolgáltatás (innen: <xliff:g id="PACKAGENAME">%1$s</xliff:g>) nem tartalmaz majd használat közbeni engedélyt a jövőbeli R buildekben. Kérjük, keresse fel a go/r-bg-fgs-restriction webhelyet, és jelentse a hibát."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Az ajánlott szint fölé szeretné emelni a hangerőt?\n\nHa hosszú időn át teszi ki magát nagy hangerőnek, azzal károsíthatja a hallását."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Szeretné használni a Kisegítő lehetőségek billentyűparancsot?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ha a gyorsparancs aktív, akkor a két hangerőgomb három másodpercig tartó együttes lenyomásával kisegítő funkciót indíthat el."</string>
@@ -1628,7 +1627,7 @@
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Bekapcsolja a következőt: <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"A(z) <xliff:g id="SERVICE">%1$s</xliff:g> kisegítő lehetőség bekapcsolásához tartsa nyomva néhány másodpercig mindkét hangerőgombot. Ez hatással lehet az eszköz működésére.\n\nEzt a gyorsparancsot a Beállítások &gt; Kisegítő lehetőségek pontban módosíthatja másik funkció használatára."</string>
- <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Bekapcsolás"</string>
+ <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Bekapcsolom"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"Nem kapcsolom be"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"BE"</string>
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"KI"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index ec56952ea4a2..6f676fd7af80 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման նմուշը: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո ձեզ կառաջարկվի ապակողպել ձեր հեռախոսը` օգտագործելով էլփոստի հաշիվ:\n\n Փորձեք կրկին <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Հեռացնել"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Ֆոնային ռեժիմում <xliff:g id="PACKAGENAME">%1$s</xliff:g>-ից գործարկված առաջին պլանի ծառայությունը հետագա R կառուցումներում թույլտվություն չի ունենա օգտագործման ընթացքում։ Անցեք go/r-bg-fgs-restriction էջ և հաղորդեք վրիպակի մասին։"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ձայնը բարձրացնե՞լ խորհուրդ տրվող մակարդակից ավել:\n\nԵրկարատև բարձրաձայն լսելը կարող է վնասել ձեր լսողությունը:"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Օգտագործե՞լ Մատչելիության դյուրանցումը։"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Հատուկ գործառույթն օգտագործելու համար սեղմեք և 3 վայրկյան սեղմած պահեք ձայնի ուժգնության երկու կոճակները, երբ գործառույթը միացված է:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 3fb2a7732f0e..3aaf2f5f6404 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\nCoba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hapus"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Layanan latar depan yang dimulai oleh latar belakang dari <xliff:g id="PACKAGENAME">%1$s</xliff:g> tidak akan memiliki izin saat-sedang-digunakan pada build R masa mendatang Lihat go/r-bg-fgs-restriction dan kirim laporan bug."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Mengeraskan volume di atas tingkat yang disarankan?\n\nMendengarkan dengan volume keras dalam waktu yang lama dapat merusak pendengaran Anda."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Aksesibilitas?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Saat pintasan aktif, menekan kedua tombol volume selama 3 detik akan memulai fitur aksesibilitas."</string>
@@ -1651,8 +1650,8 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversi Warna"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Koreksi Warna"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tombol volume yang ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> diaktifkan."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tombol volume yang ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dinonaktifkan."</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> diaktifkan."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dinonaktifkan."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua tombol volume selama tiga detik untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Pilih fitur yang akan digunakan saat mengetuk tombol aksesibilitas:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Pilih fitur yang akan digunakan dengan gestur aksesibilitas (geser ke atas dari bawah layar dengan dua jari):"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 82d6206ab625..e5e23f6e0ac3 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -237,7 +237,7 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Valkostir síma"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Skjálás"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Slökkva"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Orka"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Slökkva/endurræsa"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Endurræsa"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Neyðarsímtal"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Villutilkynning"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður þú beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjarlægja"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Forgrunnsþjónusta frá <xliff:g id="PACKAGENAME">%1$s</xliff:g> sem er ræst úr bakgrunni mun ekki hafa heimild við notkun í framtíðarútgáfum R. Farðu á go/r-bg-fgs-restriction og gefðu villuskýrslu."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Hækka hljóðstyrk umfram ráðlagðan styrk?\n\nEf hlustað er á háum hljóðstyrk í langan tíma kann það að skaða heyrnina."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Viltu nota aðgengisflýtileið?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Þegar flýtileiðin er virk er kveikt á aðgengiseiginleikanum með því að halda báðum hljóðstyrkshnöppunum inni í þrjár sekúndur."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Hafna"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ýttu á eiginleika til að byrja að nota hann:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Veldu eiginleika sem á að nota með aðgengishnappinum"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Veldu eiginleika á að nota með flýtileið hljóðstyrkstakka"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Veldu eiginleika sem á að nota með flýtileið hljóðstyrkstakka"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Slökkt hefur verið á <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Breyta flýtileiðum"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Lokið"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 80e34ef648cf..5b6b5feeb09b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1619,12 +1619,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Rimuovi"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Il servizio in primo piano avviato in background da <xliff:g id="PACKAGENAME">%1$s</xliff:g> non avrà l\'autorizzazione \"durante l\'uso\" nelle future build R. Visita la pagina go/r-bg-fgs-restriction e invia una segnalazione di bug."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vuoi aumentare il volume oltre il livello consigliato?\n\nL\'ascolto ad alto volume per lunghi periodi di tempo potrebbe danneggiare l\'udito."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usare la scorciatoia Accessibilità?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando la scorciatoia è attiva, puoi premere entrambi i pulsanti del volume per tre secondi per avviare una funzione di accessibilità."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Attivare le funzioni di accessibilità?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Se tieni premuti entrambi i tasti del volume per qualche secondo, le funzioni di accessibilità vengono attivate. Questa operazione potrebbe modificare il funzionamento del dispositivo.\n\nFunzionalità correnti:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuoi modificare le funzionalità selezionate in Impostazioni &gt; Accessibilità."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Se tieni premuti entrambi i tasti del volume per qualche secondo, vengono attivate le funzioni di accessibilità. Questa operazione potrebbe modificare il funzionamento del dispositivo.\n\nFunzioni correnti:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuoi modificare le funzioni selezionate in Impostazioni &gt; Accessibilità."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Attivare <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Se tieni premuti entrambi i tasti del volume per qualche secondo verrà attivata la funzione di accessibilità <xliff:g id="SERVICE">%1$s</xliff:g>. Questa operazione potrebbe modificare il funzionamento del dispositivo.\n\nPuoi associare questa scorciatoia a un\'altra funzionalità in Impostazioni &gt; Accessibilità."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Rifiuta"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocca una funzionalità per iniziare a usarla:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Scegli le funzionalità da usare con il pulsante Accessibilità"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Scegli le funzionalità da usare con la scorciatoia per i tasti del volume"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Scegli le funzionalità da usare con la scorciatoia dei tasti del volume"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Il servizio <xliff:g id="SERVICE_NAME">%s</xliff:g> è stato disattivato"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifica scorciatoie"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fine"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 10d3f4383069..1b3fb1ba087a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1663,7 +1663,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"הסר"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"‏לשירות שפועל בחזית מ-<xliff:g id="PACKAGENAME">%1$s</xliff:g> שהחל ברקע לא תהיה הרשאת while-in-use בגרסאות R build בעתיד. יש לעיין בכתובת go/r-bg-fgs-restriction ולהגיש דוח על באג."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"האם להעלות את עוצמת הקול מעל לרמה המומלצת?\n\nהאזנה בעוצמת קול גבוהה למשכי זמן ממושכים עלולה לפגוע בשמיעה."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"להשתמש בקיצור הדרך לתכונת הנגישות?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת הקול למשך שלוש שניות מפעילה את תכונת הנגישות."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 7f27e648b4d7..f5686c2ec12d 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1311,7 +1311,7 @@
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB デバッグを無効にする場合に選択します。"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"ワイヤレス デバッグが接続されました"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"ワイヤレス デバッグをUSB デバッグを無効にするにはここをタップしてください"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"ワイヤレス デバッグを無効にする場合に選択します。"</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"ワイヤレス デバッグを無効にするには選択します。"</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"テストハーネス モード有効"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"出荷時設定にリセットしてテストハーネス モードを無効にしてください。"</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"シリアル コンソールは有効です"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%1$d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%2$d</xliff:g>回間違えると、モバイルデバイスのロック解除にメールアカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>秒後にもう一度お試しください。"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"削除"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"今後の R ビルドでは、<xliff:g id="PACKAGENAME">%1$s</xliff:g> からバックグラウンドで開始されるフォアグラウンド サービスに「使用中のみ許可」の権限がありません。go/r-bg-fgs-restriction を確認し、バグレポートを提出してください。"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"推奨レベルを超えるまで音量を上げますか?\n\n大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ユーザー補助機能のショートカットの使用"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ショートカットが ON の場合、両方の音量ボタンを 3 秒ほど長押しするとユーザー補助機能が起動します。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index ed31a1cd3bed..3d447fc00bf0 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი ცდის შემდეგ, დაგჭირდებათ თქვენი ტელეფონის განბლოკვა ელფოსტის ანგარიშის გამოყენებით.\n\n ხელახლა სცადეთ <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ამოშლა"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g>-ის ფონურად დაწყებულ წინა პლანის სერვისს მომავალ R build-ებში გამოყენების პროცესში წვდომის ნებართვა არ ექნება. გთხოვთ, იხილოთ go/r-bg-fgs-restriction და გამოგზავნოთ ხარვეზის ანგარიში."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"გსურთ ხმის რეკომენდებულ დონეზე მაღლა აწევა?\n\nხანგრძლივად ხმამაღლა მოსმენით შესაძლოა სმენადობა დაიზიანოთ."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"გსურთ მარტივი წვდომის მალსახმობის გამოყენება?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"თუ მალსახმობი ჩართულია, ხმის ორივე ღილაკზე 3 წამის განმავლობაში დაჭერით მარტივი წვდომის ფუნქცია ჩაირთვება."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 9ada4376e50d..28409e019a59 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды есептік жазба арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Алып тастау"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Фондық режимде іске қосылған <xliff:g id="PACKAGENAME">%1$s</xliff:g> белсенді пакетінің алдағы R құрамаларында \"Пайдаланғанда ғана рұқсат ету\" рұқсаты болмайды. go/r-bg-fgs-restriction бетіне өтіп, қате туралы есеп жіберіңіз."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дыбыс деңгейін ұсынылған деңгейден көтеру керек пе?\n\nЖоғары дыбыс деңгейінде ұзақ кезеңдер бойы тыңдау есту қабілетіңізге зиян тигізуі мүмкін."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Арнайы мүмкіндік төте жолын пайдалану керек пе?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Түймелер тіркесімі қосулы кезде, екі дыбыс түймесін 3 секунд басып тұрсаңыз, \"Арнайы мүмкіндіктер\" функциясы іске қосылады."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 4fd0338b1f63..e056455f4773 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1621,7 +1621,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង។ បន្ទាប់​ពី​ការ​ព្យាយាម​មិន​ជោគជ័យ​​ច្រើនជាង <xliff:g id="NUMBER_1">%2$d</xliff:g> ដង អ្នក​នឹង​ត្រូវ​បាន​​ស្នើ​ឲ្យ​ដោះ​សោ​ទូរស័ព្ទ​របស់​អ្នក​ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី។"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"លុប​ចេញ"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"សេវាកម្ម​ផ្ទៃខាងមុខ​ដែលចាប់ផ្ដើមដោយ​ផ្ទៃខាងក្រោយ​ពី <xliff:g id="PACKAGENAME">%1$s</xliff:g> នឹង​មិនមាន​ការអនុញ្ញាត​ខណៈពេល​កំពុង​ប្រើប្រាស់​ទេ នៅក្នុង​កំណែបង្កើត R នៅពេល​អនាគត​។ សូម​មើល go/r-bg-fgs-restriction និង​ផ្ញើ​របាយការណ៍​អំពី​បញ្ហា​។"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"បង្កើន​កម្រិត​សំឡេង​លើស​ពី​កម្រិត​បាន​ផ្ដល់​យោបល់?\n\nការ​ស្ដាប់​នៅ​កម្រិត​សំឡេង​ខ្លាំង​យូរ​អាច​ធ្វើឲ្យ​ខូច​ត្រចៀក។"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ប្រើប្រាស់​ផ្លូវកាត់​ភាព​ងាយស្រួល?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"នៅពេលបើក​ផ្លូវកាត់ ការចុច​ប៊ូតុង​កម្រិតសំឡេង​ទាំងពីរ​រយៈពេល 3 វិនាទី​នឹង​ចាប់ផ្តើម​មុខងារ​ភាពងាយប្រើ។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index a1060808172a..72cf78f8275e 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1619,12 +1619,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡುವಂತೆ ನಿಮ್ಮಲ್ಲಿ ಕೇಳಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ತೆಗೆದುಹಾಕು"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> ನಿಂದ ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಪ್ರಾರಂಭಿಸಲಾದ ಮುನ್ನೆಲೆ ಸೇವೆ ಭವಿಷ್ಯದ R ಬಿಲ್ಡ್‌ಗಳಿಂದ ಬಳಕೆಯಲ್ಲಿರುವಾಗ ಅನುಮತಿಯನ್ನು ಪಡೆಯುವುದಿಲ್ಲ. go/r-bg-fgs-restriction ಅನ್ನು ನೋಡಿ ಮತ್ತು ದೋಷವರದಿಯನ್ನು ಫೈಲ್‌ ಮಾಡಿ."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ವಾಲ್ಯೂಮ್‌ ಅನ್ನು ಶಿಫಾರಸು ಮಾಡಲಾದ ಮಟ್ಟಕ್ಕಿಂತಲೂ ಹೆಚ್ಚು ಮಾಡುವುದೇ?\n\nದೀರ್ಘ ಅವಧಿಯವರೆಗೆ ಹೆಚ್ಚಿನ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಆಲಿಸುವುದರಿಂದ ನಿಮ್ಮ ಆಲಿಸುವಿಕೆ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟು ಮಾಡಬಹುದು."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸುವುದೇ?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳನ್ನು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಿದರೆ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವೊಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ."</string>
- <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆನ್ ಮಾಡುವುದೇ?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳು ಆನ್ ಆಗುತ್ತವೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\n ಪ್ರಸ್ತುತ ವೈಶಿಷ್ಟ್ಯಗಳು:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಅಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿ ಆಯ್ದ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನೀವು ಬದಲಾಯಿಸಬಹುದು."</string>
+ <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆನ್ ಮಾಡಬೇಕೇ?"</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳು ಆನ್ ಆಗುತ್ತವೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\n ಪ್ರಸ್ತುತ ವೈಶಿಷ್ಟ್ಯಗಳು:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿ ಆಯ್ದ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನೀವು ಬದಲಾಯಿಸಬಹುದು."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> ಅನ್ನು ಆನ್‌ ಮಾಡುವುದೇ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವಾದ <xliff:g id="SERVICE">%1$s</xliff:g> ಆನ್ ಆಗುತ್ತದೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\nನೀವು ಈ ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಅಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿನ ಮತ್ತೊಂದು ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಬದಲಾಯಿಸಬಹುದು."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 7ea8b4313f81..63c3a379ad66 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금해제해야 합니다.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"삭제"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"향후 R 빌드에서는 백그라운드에서 시작된 <xliff:g id="PACKAGENAME">%1$s</xliff:g>의 포그라운드 서비스에 더 이상 사용 중인 상태에서 필요한 권한이 부여되지 않습니다. go/r-bg-fgs-restriction 페이지에서 버그 신고를 제출하세요."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"권장 수준 이상으로 볼륨을 높이시겠습니까?\n\n높은 볼륨으로 장시간 청취하면 청력에 손상이 올 수 있습니다."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"접근성 단축키를 사용하시겠습니까?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"단축키가 사용 설정된 경우 볼륨 버튼 두 개를 동시에 3초간 누르면 접근성 기능이 시작됩니다."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index dbbc14f706c0..7fcad66d0003 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1309,7 +1309,7 @@
<string name="adb_active_notification_title" msgid="408390247354560331">"Мүчүлүштүктөр USB аркылуу оңдолууда"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Өчүрүү үчүн тийип коюңуз"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB аркылуу мүчүлүштүктөрдү оңдоону өчүрүүнү тандаңыз."</string>
- <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Мүчүлүштүктөрдү зымсыз оңдоо иштетилди"</string>
+ <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Мүчүлүштүктөр Wi-Fi аркылуу оңдолууда"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Мүчүлүштүктөрдү зымсыз оңдоону өчүрүү үчүн таптап коюңуз"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Мүчүлүштүктөрдү Wi-Fi аркылуу оңдоону өчүрүңүз."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Сыноо программасынын режими иштетилди"</string>
@@ -1619,17 +1619,16 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес көрсөтүлгөндөн кийин, телефондун кулпусун ачуу үчүн Google аккаунтуңузга кирүүгө туура келет.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин кайталап көрсөңүз болот."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Алып салуу"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Фондогу <xliff:g id="PACKAGENAME">%1$s</xliff:g> кызматы активдүү режимде иштеп баштап, кийинки R курамаларында колдонуу учурунда уруксаты болбойт. Төмөнкү бөлүмгө өтүп, мүчүлүштүк тууралуу кабарды тапшырыңыз: go/r-bg-fgs-restriction."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Сунушталган деңгээлден да катуулатып уккуңуз келеби?\n\nМузыканы узакка чейин катуу уксаңыз, угууңуз начарлап кетиши мүмкүн."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ыкчам иштетесизби?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең 3 секунддай коё бербей басып туруңуз."</string>
- <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Атайын мүмкүнчүлүктөр күйгүзүлсүнбү?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып турса, атайын мүмкүнчүлүктөр күйгүзүлөт. Бул түзмөгүңүздүн ишин өзгөртүшү мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды Жөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнөн өзгөртө аласыз."</string>
+ <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Атайын мүмкүнчүлүктөрдү иштетесизби?"</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Атайын мүмкүнчүлүктөр функциясын иштетүү үчүн, үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды өзгөртүү үчүн, Жөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> күйгүзүлсүнбү?"</string>
- <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып турса, <xliff:g id="SERVICE">%1$s</xliff:g>, атайын мүмкүнчүлүктөр күйгүзүлөт. Бул түзмөгүңүздүн ишин өзгөртүшү мүмкүн.\n\nБул ыкчам баскычты Жөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнөн башка функцияга өзгөртө аласыз."</string>
- <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Күйгүзүлсүн"</string>
- <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Күйгүзүлбөсүн"</string>
+ <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматын иштетүү үчүн, үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nБаскычтардын ушул айкалышын башка функцияга дайындоо үчүн, Жөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
+ <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ооба"</string>
+ <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Жок"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"КҮЙҮК"</string>
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"ӨЧҮК"</string>
<string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматына түзмөгүңүздү толугу менен көзөмөлдөөгө уруксат бересизби?"</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Жок"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны колдонуп баштоо үчүн аны таптап коюңуз:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Атайын мүмкүнчүлүктөр баскычы менен колдонгуңуз келген функцияларды тандаңыз"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Үн деңгээлинин баскычтары менен колдонгуңуз келген функцияларды тандаңыз"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Үндү катуулатуу/акырындатуу баскычтары менен кайсы функцияларды иштеткиңиз келет?"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> өчүрүлдү"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Кыска жолдорду түзөтүү"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Бүттү"</string>
@@ -1651,8 +1650,8 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Кыска жолду колдонуу"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Түстү инверсиялоо"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Түсүн тууралоо"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтарын басып туруңуз. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтарын басып туруңуз. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын колдонуу үчүн үнүн чоңойтуп/кичирейтүү баскычтарын үч секунд коё бербей басып туруңуз"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Атайын мүмкүнчүлүктөр баскычын таптаганыңызда иштей турган функцияны тандаңыз:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Атайын мүмкүнчүлүктөр жаңсоосу үчүн функцияны тандаңыз (эки манжаңыз менен экрандын ылдый жагынан өйдө карай сүрүңүз):"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 278237954a53..66ec0e691eed 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1311,7 +1311,7 @@
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"ເລືອກເພື່ອປິດການດີບັກຜ່ານ USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"ເຊື່ອມຕໍ່ການດີບັກໄຮ້ສາຍແລ້ວ"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"ແຕະເພື່ອປິດການດີບັກໄຮ້ສາຍ"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"ເລືອກປິດການປິດການນຳໃຊ້ການດີບັກໄຮ້ສາຍ."</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"ເລືອກເພື່ອປິດການນຳໃຊ້ການດີບັກໄຮ້ສາຍ."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"ເປີດໃຊ້ໂໝດ Test Harness ແລ້ວ"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"ດຳເນີນການຣີເຊັດເປັນຄ່າຈາກໂຮງງານເພື່ອປິດການນຳໃຊ້ໂໝດ Test Harness."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"ເປີດນຳໃຊ້ຊີຣຽວຄອນໂຊແລ້ວ"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຂອງທ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກຄວາມພະຍາຍາມອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກໂທລະສັບຂອງທ່ານດ້ວຍບັນຊີອີເມວ.\n\n ລອງໃໝ່ອີກຄັ້ງໃນ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ລຶບອອກ"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"ບໍລິການພື້ນໜ້າທີ່ເລີ່ມຕົ້ນຈາກພື້ນຫຼັງຈາກ <xliff:g id="PACKAGENAME">%1$s</xliff:g> ຈະບໍ່ມີສິດອະນຸຍາດໃນຂະນະທີ່ໃຊ້ໃນ R builds ໃນອະນາຄົດ. ກະລຸນາອ່ານ go/r-bg-fgs-restriction ແລະ ລາຍງານຂໍ້ຜິດພາດ."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ເພີ່ມ​ລະ​ດັບ​ສຽງ​ໃຫ້​ເກີນກວ່າ​ລະ​ດັບ​ທີ່​ແນະ​ນຳ​ບໍ?\n\n​ການ​ຮັບ​ຟັງ​ສຽງ​ໃນ​ລະ​ດັບ​ທີ່​ສູງ​ເປັນ​ໄລ​ຍະ​ເວ​ລາ​ດົນ​​ອາດ​ເຮັດ​ໃຫ້​ການ​ຟັງ​ຂອງ​ທ່ານ​ມີ​ບັນ​ຫາ​ໄດ້."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ໃຊ້ປຸ່ມລັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ເມື່ອເປີດໃຊ້ທາງລັດແລ້ວ, ການກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີຈະເປັນການເລີ່ມຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a0137c165a4b..4f71c361f98a 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1663,7 +1663,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%1$d</xliff:g> k. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami „Google“ prisijungimo duomenis.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Pašalinti"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Fone pradėtai priekinio plano paslaugai iš „<xliff:g id="PACKAGENAME">%1$s</xliff:g>“ nebus suteiktas leidimas naudojimo metu būsimose R versijose. Apsilankykite go/r-bg-fgs-restriction ir pateikite pranešimą apie riktą."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Padidinti garsą daugiau nei rekomenduojamas lygis?\n\nIlgai klausydami dideliu garsu galite pažeisti klausą."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Naudoti spartųjį pritaikymo neįgaliesiems klavišą?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kai spartusis klavišas įjungtas, paspaudus abu garsumo mygtukus ir palaikius 3 sekundes bus įjungta pritaikymo neįgaliesiems funkcija."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 09942a99be37..f4938cc0a964 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1641,7 +1641,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%1$d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> neveiksmīgiem mēģinājumiem tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundēm."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">"  — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Noņemt"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Fonā sāktam priekšplāna pakalpojumam no pakotnes <xliff:g id="PACKAGENAME">%1$s</xliff:g> nebūs atļaujas “while-in-use” turpmākajās R versijās. Lūdzu, skatiet vietni go/r-bg-fgs-restriction un iesniedziet kļūdas pārskatu."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vai palielināt skaļumu virs ieteicamā līmeņa?\n\nIlgstoši klausoties skaņu lielā skaļumā, var tikt bojāta dzirde."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vai izmantot pieejamības saīsni?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad īsinājumtaustiņš ir ieslēgts, nospiežot abas skaļuma pogas un 3 sekundes turot tās, tiks aktivizēta pieejamības funkcija."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index bfad9e964b93..f382ee90378a 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -243,7 +243,7 @@
<string name="global_action_bug_report" msgid="5127867163044170003">"Извештај за грешка"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Завршете ја сесијата"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Слика од екранот"</string>
- <string name="bugreport_title" msgid="8549990811777373050">"Извештај за грешка"</string>
+ <string name="bugreport_title" msgid="8549990811777373050">"Извештај за грешки"</string>
<string name="bugreport_message" msgid="5212529146119624326">"Ова ќе собира информации за моменталната состојба на вашиот уред, за да ги испрати како порака по е-пошта. Тоа ќе одземе малку време почнувајќи од извештајот за грешки додека не се подготви за праќање; бидете трпеливи."</string>
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"Интерактивен извештај"</string>
<string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Користете го ова во повеќето ситуации. Ви дозволува да го следите напредокот на извештајот, да внесете повеќе детали во врска со проблемот и да сликате слики од екранот. Може да испушти некои помалку користени делови за коишто е потребно долго време за да се пријават."</string>
@@ -1309,7 +1309,7 @@
<string name="adb_active_notification_title" msgid="408390247354560331">"Поврзано е отстранување грешки преку USB"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Допрете за да го исклучите"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Изберете за да се оневозможи отстранување грешки на USB."</string>
- <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Безжичното отстранување грешки е поврзано"</string>
+ <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Поврзано е безжично отстранување грешки"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Допрете за да се исклучи безжичното отстранување грешки"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Изберете за да се оневозможи безжично отстранување грешки."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Овозможен е режимот на рамка за тестирање"</string>
@@ -1586,7 +1586,7 @@
</plurals>
<string name="kg_pattern_instructions" msgid="8366024510502517748">"Употреби ја својата шема"</string>
<string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Внеси PIN на SIM картичка"</string>
- <string name="kg_pin_instructions" msgid="7355933174673539021">"Внеси PIN"</string>
+ <string name="kg_pin_instructions" msgid="7355933174673539021">"Впишете PIN"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"Внеси лозинка"</string>
<string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM картичката е сега оневозможена. Внесете ПУК код за да продолжите. Контактирајте го операторот за детали."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Внеси посакуван PIN код"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Погрешно сте ја употребиле вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараат од вас да го отклучите телефонот со користење сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Отстрани"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Услугата од преден план започната во заднина од <xliff:g id="PACKAGENAME">%1$s</xliff:g> нема да има дозола за „додека се користи“ во идните R-верзии. Погледнете на go/r-bg-fgs-restriction и испратете извештај за грешка."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да го зголемиме звукот над препорачаното ниво?\n\nСлушањето звуци со голема јачина подолги периоди може да ви го оштети сетилото за слух."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Да се користи кратенка за „Пристапност“?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Кога е вклучена кратенката, ако ги притиснете двете копчиња за јачина на звук во времетраење од 3 секунди, ќе се стартува функција за пристапност."</string>
@@ -1759,7 +1758,7 @@
<string name="print_service_installed_title" msgid="6134880817336942482">"Услугате <xliff:g id="NAME">%s</xliff:g> е инсталирана"</string>
<string name="print_service_installed_message" msgid="7005672469916968131">"Допри да се овозможи"</string>
<string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"Внесете PIN на админстратор"</string>
- <string name="restr_pin_enter_pin" msgid="373139384161304555">"Внеси PIN"</string>
+ <string name="restr_pin_enter_pin" msgid="373139384161304555">"Впишете PIN"</string>
<string name="restr_pin_incorrect" msgid="3861383632940852496">"Неточно"</string>
<string name="restr_pin_enter_old_pin" msgid="7537079094090650967">"Тековен PIN"</string>
<string name="restr_pin_enter_new_pin" msgid="3267614461844565431">"Нов PIN"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index ac32b3cb378d..496ba21a05ae 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -175,7 +175,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"ഒരുപാട് <xliff:g id="CONTENT_TYPE">%s</xliff:g> ഇല്ലാതാക്കാൻ ശ്രമിച്ചു."</string>
<string name="low_memory" product="tablet" msgid="5557552311566179924">"ടാബ്‌ലെറ്റ് സ്റ്റോറേജ് കഴിഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ ചില ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
<string name="low_memory" product="watch" msgid="3479447988234030194">"വാച്ചിലെ സ്റ്റോറേജ് നിറഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ കുറച്ച് ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
- <string name="low_memory" product="tv" msgid="6663680413790323318">"Android ടിവി ഉപകരണ സ്‌റ്റോറേജ് നിറഞ്ഞിരിക്കുന്നു. ഇടമുണ്ടാക്കാൻ കുറച്ച് ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
+ <string name="low_memory" product="tv" msgid="6663680413790323318">"Android TV ഉപകരണ സ്‌റ്റോറേജ് നിറഞ്ഞിരിക്കുന്നു. ഇടമുണ്ടാക്കാൻ കുറച്ച് ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
<string name="low_memory" product="default" msgid="2539532364144025569">"ഫോൺ സ്റ്റോറേജ് കഴിഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ ചില ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
<item quantity="other">സർട്ടിഫിക്കറ്റ് അതോറിറ്റികൾ ഇൻസ്റ്റാൾ ചെയ്തു</item>
@@ -206,7 +206,7 @@
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ഓണാക്കുക"</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>
+ <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ഓപ്‌ഷനുകൾ"</string>
<string name="power_dialog" product="default" msgid="1107775420270203046">"ഫോൺ ഓപ്‌ഷനുകൾ"</string>
<string name="silent_mode" msgid="8796112363642579333">"നിശബ്‌ദ മോഡ്"</string>
<string name="turn_on_radio" msgid="2961717788170634233">"വയർലെസ് ഓണാക്കുക"</string>
@@ -233,7 +233,7 @@
<string name="recent_tasks_title" msgid="8183172372995396653">"അടുത്തിടെയുള്ളത്"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"അടുത്തിടെയുള്ള ആപ്സൊന്നുമില്ല."</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"ടാബ്‌ലെറ്റ് ഓപ്‌ഷനുകൾ"</string>
- <string name="global_actions" product="tv" msgid="3871763739487450369">"Android ടിവി ഓപ്‌ഷനുകൾ"</string>
+ <string name="global_actions" product="tv" msgid="3871763739487450369">"Android TV ഓപ്‌ഷനുകൾ"</string>
<string name="global_actions" product="default" msgid="6410072189971495460">"ഫോൺ ഓപ്‌ഷനുകൾ"</string>
<string name="global_action_lock" msgid="6949357274257655383">"സ്‌ക്രീൻ ലോക്ക്"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"പവർ ഓഫാക്കുക"</string>
@@ -293,7 +293,7 @@
<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="permgrouplab_contacts" msgid="4254143639307316920">"കോൺടാക്റ്റ്"</string>
+ <string name="permgrouplab_contacts" msgid="4254143639307316920">"കോൺടാക്റ്റുകൾ"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്‌സസ്സ് ചെയ്യുക"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"ലൊക്കേഷൻ"</string>
<string name="permgroupdesc_location" msgid="1995955142118450685">"ഈ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ആക്സസ് ചെയ്യാൻ"</string>
@@ -393,7 +393,7 @@
<string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"സിസ്‌റ്റം ബൂട്ടുചെയ്യുന്നത് പൂർത്തിയാകുമ്പോൾ തന്നെ സ്വയം ആരംഭിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് ഫോൺ ആരംഭിക്കുന്നതിന് കൂടുതൽ ദൈർഘ്യമെടുക്കാം ഒപ്പം പ്രവർത്തിക്കുമ്പോഴെല്ലാം മൊത്തം ഫോണിന്റെ മൊത്തത്തിലുള്ള വേഗത കുറയ്ക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കും."</string>
<string name="permlab_broadcastSticky" msgid="4552241916400572230">"സ്റ്റിക്കി പ്രക്ഷേപണം അയ‌യ്‌ക്കുക"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"സ്റ്റിക്കി പ്രക്ഷേപണങ്ങൾ അയയ്‌ക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു, പ്രക്ഷേപണം അവസാനിച്ചതിനുശേഷവും അത് നിലനിൽക്കുന്നു. അമിതോപയോഗം വളരെയധികം മെമ്മറി ഉപയോഗിക്കുന്നതിനാൽ, അത് ടാബ്‌ലെറ്റിന്റെ പ്രവർത്തനത്തെ മന്ദഗതിയിലാക്കുകയോ അസ്ഥിരമാക്കുകയോ ചെയ്യാം."</string>
- <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"പ്രക്ഷേപണം അവസാനിച്ച ശേഷവും അവശേഷിക്കുന്ന സ്‌റ്റിക്കി പ്രക്ഷേപണങ്ങൾ അയയ്‌ക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. Android ടിവിയുടെ അമിതമായ ഉപയോഗം ഒരുപാട് മെമ്മറി ഉപയോഗിക്കാൻ കാരണമാകുകയും ടിവിയുടെ വേഗത കുറയ്‌ക്കുകയോ അതിനെ അസ്ഥിരമാക്കുകയോ ചെയ്‌തേക്കാം."</string>
+ <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"പ്രക്ഷേപണം അവസാനിച്ച ശേഷവും അവശേഷിക്കുന്ന സ്‌റ്റിക്കി പ്രക്ഷേപണങ്ങൾ അയയ്‌ക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. Android TV-യുടെ അമിതമായ ഉപയോഗം ഒരുപാട് മെമ്മറി ഉപയോഗിക്കാൻ കാരണമാകുകയും ടിവിയുടെ വേഗത കുറയ്‌ക്കുകയോ അതിനെ അസ്ഥിരമാക്കുകയോ ചെയ്‌തേക്കാം."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"സ്റ്റിക്കി പ്രക്ഷേപണങ്ങൾ അയയ്‌ക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു, പ്രക്ഷേപണം അവസാനിച്ചതിനുശേഷവും അത് നിലനിൽക്കുന്നു. അമിതോപയോഗം വളരെയധികം മെമ്മറി ഉപയോഗിക്കുന്നതിനാൽ, അത് ഫോണിന്റെ പ്രവർത്തനത്തെ മന്ദഗതിയിലാക്കുകയോ അസ്ഥിരമാക്കുകയോ ചെയ്യാം."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ റീഡുചെയ്യുക"</string>
<string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ടാബ്‌ലെറ്റിൽ സംഭരിച്ച നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ വായിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ കോണ്ടാക്റ്റുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളിലേക്കുള്ള ആക്സസും ആപ്പുകൾക്ക് ഉണ്ടായിരിക്കും. നിങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്‍ത ആപ്പുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളും ഇതിൽ ഉൾപ്പെട്ടേക്കാം. നിങ്ങളുടെ കോണ്ടാക്റ്റ് ഡാറ്റ സംരക്ഷിക്കാൻ ആപ്പുകളെ ഈ അനുമതി അനുവദിക്കുന്നു, നിങ്ങളുടെ അറിവില്ലാതെ, ദോഷകരമായ ആപ്പുകൾ കോണ്ടാക്റ്റ് ഡാറ്റ പങ്കിടുകയും ചെയ്‌തേക്കാം."</string>
@@ -407,17 +407,17 @@
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ഈ ആപ്പിന് നിങ്ങളുടെ കോൾ ചരിത്രം വായിക്കാൻ കഴിയും."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"കോൾ ചരിത്രം റൈറ്റ് ചെയ്യുക"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"ഇൻകമ്മിംഗ്-ഔട്ട്ഗോയിംഗ് കോളുകളെക്കുറിച്ചുള്ള ഡാറ്റയുൾപ്പെടെയുള്ള നിങ്ങളുടെ ടാബ്‌ലെറ്റിന്‍റെ കോൾ ചരിത്രം പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു.ഇതു വഴി കോൾ ചരിത്ര ഡാറ്റകൾ പരിഷ്‌ക്കരിക്കാനും ഇല്ലാതാക്കാനും ദോഷകരമായ അപ്ലിക്കേഷനുകൾക്ക് കഴിഞ്ഞേയ്ക്കാം."</string>
- <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"ഇൻകമിംഗ്, ഔട്ട്‌ഗോയിംഗ് കോളുകളെക്കുറിച്ചുള്ള ഡാറ്റ ഉൾപ്പെടെ നിങ്ങളുടെ Android ടിവിയിലെ കോൾ ചരിത്രം പരിഷ്‌ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ കോൾ ചരിത്രം മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ ദോഷകരമായ ആപ്പുകൾ ഇത് ഉപയോഗിച്ചേക്കാം."</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"ഇൻകമിംഗ്, ഔട്ട്‌ഗോയിംഗ് കോളുകളെക്കുറിച്ചുള്ള ഡാറ്റ ഉൾപ്പെടെ നിങ്ങളുടെ Android TV-യിലെ കോൾ ചരിത്രം പരിഷ്‌ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ കോൾ ചരിത്രം മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ ദോഷകരമായ ആപ്പുകൾ ഇത് ഉപയോഗിച്ചേക്കാം."</string>
<string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"ഇൻകമ്മിംഗ്-ഔട്ട്ഗോയിംഗ് കോളുകളെക്കുറിച്ചുള്ള ഡാറ്റയുൾപ്പെടെയുള്ള നിങ്ങളുടെ ഫോണിന്‍റെ കോൾ ചരിത്രം പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു.ഇതു വഴി കോൾ ചരിത്ര ഡാറ്റകൾ പരിഷ്‌ക്കരിക്കാനും ഇല്ലാതാക്കാനും ദോഷകരമായ അപ്ലിക്കേഷനുകൾക്ക് കഴിഞ്ഞേയ്ക്കാം."</string>
<string name="permlab_bodySensors" msgid="3411035315357380862">"ശരീര സെൻസറുകൾ (ഹൃദയമിടിപ്പ് നിരക്ക് മോണിറ്ററുകൾ പോലെ) ആക്സസ് ചെയ്യുക"</string>
<string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"നിങ്ങളുടെ ഹൃദയമിടിപ്പ് പോലുള്ള ശാരീരികാവസ്ഥ നിരീക്ഷിക്കാൻ സെൻസറുകളിൽ നിന്ന് വിവരം ആക്‌സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"കലണ്ടർ ഇവന്റുകളും വിശദാംശങ്ങളും വായിക്കുക"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"ഈ ആപ്പിന് നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ സംഭരിച്ചിരിക്കുന്ന എല്ലാ കലണ്ടർ ഇവന്റുകളും വായിക്കാനും നിങ്ങളുടെ കലണ്ടർ വിവരങ്ങൾ പങ്കിടാനും അല്ലെങ്കിൽ സംരക്ഷിക്കാനും കഴിയും."</string>
- <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ഈ ആപ്പിന് നിങ്ങളുടെ Android ടിവിയിൽ സംഭരിച്ചിരിക്കുന്ന എല്ലാ കലണ്ടർ ഇവന്റുകളും വായിക്കാനും നിങ്ങളുടെ കലണ്ടർ ഡാറ്റ പങ്കിടാനോ സംരക്ഷിക്കാനോ സാധിക്കുകയും ചെയ്യും."</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ഈ ആപ്പിന് നിങ്ങളുടെ Android TV-യിൽ സംഭരിച്ചിരിക്കുന്ന എല്ലാ കലണ്ടർ ഇവന്റുകളും വായിക്കാനും നിങ്ങളുടെ കലണ്ടർ ഡാറ്റ പങ്കിടാനോ സംരക്ഷിക്കാനോ സാധിക്കുകയും ചെയ്യും."</string>
<string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"ഈ ആപ്പിന് നിങ്ങളുടെ ഫോണിൽ സംഭരിച്ചിരിക്കുന്ന എല്ലാ കലണ്ടർ ഇവന്റുകളും വായിക്കാനും നിങ്ങളുടെ കലണ്ടർ വിവരങ്ങൾ പങ്കിടാനും അല്ലെങ്കിൽ സംരക്ഷിക്കാനും കഴിയും."</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"ഉടമകളുടെ അറിവില്ലാതെ കലണ്ടർ ഇവന്റുകൾ ചേർക്കുകയോ പരിഷ്‌ക്കരിക്കുകയോ ചെയ്‌ത് അതിഥികൾക്ക് ഇമെയിൽ അയയ്‌ക്കുക"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ഈ ആപ്പിന്, നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ കലണ്ടർ ഇവന്റുകൾ ചേർക്കാനോ നീക്കംചെയ്യാനോ മാറ്റാനോ കഴിയും. കലണ്ടർ ഉടമകളിൽ നിന്നാണ് വരുന്നതെന്ന് തോന്നിപ്പിക്കാവുന്ന സന്ദേശങ്ങൾ അയയ്ക്കാനോ ഉടമകളെ അറിയിക്കാതെ അവരുടെ ഇവന്റുകളെ മാറ്റാനോ ഈ ആപ്പിന് കഴിയും."</string>
- <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"നിങ്ങളുടെ Android ടിവിയിൽ കലണ്ടർ ഇവന്റുകൾ ചേർക്കാനും നീക്കം ചെയ്യാനും മാറ്റാനും ഈ ആപ്പിന് കഴിയും. കലണ്ടർ ഉടമകളിൽ നിന്ന് വരുന്നതെന്ന് തോന്നിപ്പിക്കുന്ന സന്ദേശങ്ങൾ അയയ്‌ക്കാനോ ഉടമകൾക്ക് അറിയിപ്പ് നൽകാതെ ഇവന്റുകൾ മാറ്റാനോ ഈ ആപ്പിന് കഴിയും."</string>
+ <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"നിങ്ങളുടെ Android TV-യിൽ കലണ്ടർ ഇവന്റുകൾ ചേർക്കാനും നീക്കം ചെയ്യാനും മാറ്റാനും ഈ ആപ്പിന് കഴിയും. കലണ്ടർ ഉടമകളിൽ നിന്ന് വരുന്നതെന്ന് തോന്നിപ്പിക്കുന്ന സന്ദേശങ്ങൾ അയയ്‌ക്കാനോ ഉടമകൾക്ക് അറിയിപ്പ് നൽകാതെ ഇവന്റുകൾ മാറ്റാനോ ഈ ആപ്പിന് കഴിയും."</string>
<string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ഈ ആപ്പിന്, നിങ്ങളുടെ ഫോണിൽ കലണ്ടർ ഇവന്റുകൾ ചേർക്കാനോ നീക്കംചെയ്യാനോ മാറ്റാനോ കഴിയും. കലണ്ടർ ഉടമകളിൽ നിന്നാണ് വരുന്നതെന്ന് തോന്നിപ്പിക്കാവുന്ന സന്ദേശങ്ങൾ അയയ്ക്കാനോ ഉടമകളെ അറിയിക്കാതെ അവരുടെ ഇവന്റുകളെ മാറ്റാനോ ഈ ആപ്പിന് കഴിയും."</string>
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ലൊക്കേഷൻ ദാതാവിന്റെ അധിക കമാൻഡുകൾ ആക്‌സസ്സുചെയ്യുക"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ലൊക്കേഷൻ ദാതാവിന്റെ അധിക കമാൻഡുകൾ ആക്‌സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് GPS-ന്റെയോ മറ്റ് ലൊക്കേഷൻ ഉറവിടങ്ങളുടെയോ പ്രവർത്തനത്തിൽ ഇടപെടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്."</string>
@@ -462,15 +462,15 @@
<string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"ഉപകരണത്തിന്റെ ഫോൺ നമ്പറുകൾ ആക്‌സസ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"കാറിലെ സ്ക്രീൻ ഓണാക്കി വയ്ക്കുക"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1527660973931694000">"ഉറങ്ങുന്നതിൽ നിന്ന് ടാബ്‌ലെറ്റിനെ തടയുക"</string>
- <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"നിങ്ങളുടെ Android ടിവി ഉറങ്ങുന്നതിൽ നിന്ന് തടയുക"</string>
+ <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"നിങ്ങളുടെ Android TV ഉറങ്ങുന്നതിൽ നിന്ന് തടയുക"</string>
<string name="permlab_wakeLock" product="default" msgid="569409726861695115">"ഉറങ്ങുന്നതിൽ നിന്ന് ഫോണിനെ തടയുക"</string>
<string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"കാറിലെ സ്ക്രീൻ ഓണാക്കി വയ്ക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"ടാബ്‌ലെറ്റ് സുഷുപ്തിയിലാകുന്നതിൽ നിന്നും തടയുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"നിങ്ങളുടെ Android ടിവിയെ ഉറങ്ങുന്നതിൽ നിന്ന് തടയാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"നിങ്ങളുടെ Android TV-യെ ഉറങ്ങുന്നതിൽ നിന്ന് തടയാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"ഫോൺ സുഷുപ്തിയിലാകുന്നതിൽ നിന്നും തടയുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_transmitIr" msgid="8077196086358004010">"ഇൻഫ്രാറെഡ് അയയ്‌ക്കുക"</string>
<string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"ടാബ്‌ലെറ്റിന്റെ ഇൻഫ്രാറെഡ് ട്രാൻസ്‌മിറ്റർ ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"നിങ്ങളുടെ Android ടിവിയുടെ ഇൻഫ്രാറെഡ് ട്രാൻസ്‌മിറ്റർ ഉപയോഗിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"നിങ്ങളുടെ Android TV-യുടെ ഇൻഫ്രാറെഡ് ട്രാൻസ്‌മിറ്റർ ഉപയോഗിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"ഫോണിന്റെ ഇൻഫ്രാറെഡ് ട്രാൻസ്‌മിറ്റർ ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_setWallpaper" msgid="6959514622698794511">"വാൾപേപ്പർ സജ്ജീകരിക്കുക"</string>
<string name="permdesc_setWallpaper" msgid="2973996714129021397">"സിസ്‌റ്റം വാൾപേപ്പറിനെ സജ്ജീകരിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
@@ -478,11 +478,11 @@
<string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"സിസ്‌റ്റം വലുപ്പ സൂചനകളെ സജ്ജീകരിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_setTimeZone" msgid="7922618798611542432">"സമയ മേഖല സജ്ജീകരിക്കുക"</string>
<string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"ടാബ്‌ലെറ്റിന്റെ സമയ മേഖലയെ മാറ്റുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"നിങ്ങളുടെ Android ടിവിയുടെ സമയമേഖല മാറ്റാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"നിങ്ങളുടെ Android TV-യുടെ സമയമേഖല മാറ്റാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"ഫോണിന്റെ സമയ മേഖലയെ മാറ്റുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"ഉപകരണത്തിലെ അക്കൗണ്ടുകൾ കണ്ടെത്തുക"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"ടാബ്‌ലെറ്റ് തിരിച്ചറിയുന്ന അക്കൗണ്ടുകളുടെ ലിസ്റ്റ് നേടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇതിൽ നിങ്ങൾ ഇൻസ്റ്റാളുചെയ്‌ത അപ്ലിക്കേഷനുകൾ സൃഷ്‌ടിച്ച എല്ലാ അക്കൗണ്ടുകളും ഉൾപ്പെടാം."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"നിങ്ങളുടെ Android ടിവി തിരിച്ചറിയുന്ന അക്കൗണ്ടുകളുടെ ലിസ്‌റ്റ് നേടാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങൾ ഇൻസ്‌റ്റാൾ ചെയ്‌ത ആപ്പുകൾ സൃഷ്‌ടിച്ച ഏത് അക്കൗണ്ടുകളും ഇതിൽ ഉൾപ്പെടാം."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"നിങ്ങളുടെ Android TV തിരിച്ചറിയുന്ന അക്കൗണ്ടുകളുടെ ലിസ്‌റ്റ് നേടാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങൾ ഇൻസ്‌റ്റാൾ ചെയ്‌ത ആപ്പുകൾ സൃഷ്‌ടിച്ച ഏത് അക്കൗണ്ടുകളും ഇതിൽ ഉൾപ്പെടാം."</string>
<string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"ഫോൺ തിരിച്ചറിയുന്ന അക്കൗണ്ടുകളുടെ ലിസ്റ്റ് നേടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇതിൽ നിങ്ങൾ ഇൻസ്റ്റാളുചെയ്‌ത അപ്ലിക്കേഷനുകൾ സൃഷ്‌ടിച്ച എല്ലാ അക്കൗണ്ടുകളും ഉൾപ്പെടാം."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"നെറ്റ്‌വർക്ക് കണക്ഷനുകൾ കാണുക"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"ഏതെല്ലാം നെറ്റ്‌വർക്കുകൾ നിലവിലുണ്ടെന്നതും കണക്റ്റുചെയ്‌തിട്ടുണ്ടെന്നതും പോലുള്ള നെറ്റ്‌വർക്ക് കണക്ഷനുകളെക്കുറിച്ചുള്ള വിവരം കാണാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
@@ -508,11 +508,11 @@
<string name="permdesc_accessWimaxState" msgid="5372734776802067708">"WiMAX പ്രവർത്തനക്ഷമമാണോയെന്നതും കണക്റ്റുചെയ്‌തിരിക്കുന്ന ഏതെങ്കിലും WiMAX നെറ്റ്‌വർക്കുകളെക്കുറിച്ചുള്ള വിവരങ്ങളും നിർണ്ണയിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_changeWimaxState" msgid="6223305780806267462">"WiMAX നില മാറ്റുക"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"WiMAX നെറ്റ്‌വർക്കുകളിലേക്ക് ടാബ്‌ലെറ്റ് കണക്റ്റുചെയ്യാനും അതിൽ നിന്ന് വിച്ഛേദിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"WiMAX നെറ്റ്‌വർക്കുകളിലേക്ക് നിങ്ങളുടെ Android ടിവി കണക്‌റ്റ് ചെയ്യാനും അതിൽ നിന്ന് Android ടിവിയെ വിച്‌ഛേദിക്കാനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"WiMAX നെറ്റ്‌വർക്കുകളിലേക്ക് നിങ്ങളുടെ Android TV കണക്‌റ്റ് ചെയ്യാനും അതിൽ നിന്ന് Android TV-യെ വിച്‌ഛേദിക്കാനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"WiMAX നെറ്റ്‌വർക്കുകളിലേക്ക് ഫോൺ കണക്റ്റുചെയ്യാനും അതിൽ നിന്ന് വിച്ഛേദിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_bluetooth" msgid="586333280736937209">"ബ്ലൂടൂത്ത് ഉപകരണങ്ങളുമായി ജോടിയാക്കുക"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ടാബ്‌ലെറ്റിലെ ബ്ലൂടൂത്ത് കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ നടത്തി അംഗീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"നിങ്ങളുടെ Android ടിവിയിലെ Bluetooth കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ സൃഷ്‌ടിക്കാനും അംഗീകരിക്കാനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"നിങ്ങളുടെ Android TV-യിലെ Bluetooth കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ സൃഷ്‌ടിക്കാനും അംഗീകരിക്കാനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ഫോണിലെ ബ്ലൂടൂത്ത് കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ നടത്തി അംഗീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"തിരഞ്ഞെടുത്ത NFC പേയ്‌മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"റൂട്ട് ലക്ഷ്യസ്ഥാനം, രജിസ്‌റ്റർ ചെയ്തിരിക്കുന്ന സഹായങ്ങൾ എന്നിവ പോലുള്ള, തിരഞ്ഞെടുത്ത NFC പേയ്‌മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ ലഭിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
@@ -673,10 +673,10 @@
<string name="policydesc_limitPassword" msgid="4105491021115793793">"സ്‌ക്രീൻ ലോക്ക് പാസ്‌വേഡുകളിലും PIN-കളിലും അനുവദിച്ചിരിക്കുന്ന ദൈർഘ്യവും പ്രതീകങ്ങളും നിയന്ത്രിക്കുക."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"സ്‌ക്രീൻ അൺലോക്ക് ശ്രമങ്ങൾ നിരീക്ഷിക്കുക"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക, വളരെയധികം തെറ്റായ പാസ്‌വ്ഡുകൾ ടൈപ്പുചെയ്‌തിട്ടുണ്ടെങ്കിൽ ടാബ്‌ലെറ്റ് ലോക്കുചെയ്യുകയോ ടാബ്‌ലെറ്റിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോ ചെയ്യുക."</string>
- <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"സ്‌ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android ടിവി ലോക്ക് ചെയ്യുകയോ Android ടിവിയിലെ എല്ലാ ഡാറ്റയും മായ്‌ക്കുകയോ ചെയ്യുക."</string>
+ <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"സ്‌ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android TV ലോക്ക് ചെയ്യുകയോ Android TV-യിലെ എല്ലാ ഡാറ്റയും മായ്‌ക്കുകയോ ചെയ്യുക."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക, വളരെയധികം തെറ്റായ പാസ്‌വ്ഡുകൾ ടൈപ്പുചെയ്‌തിട്ടുണ്ടെങ്കിൽ ഫോൺ ലോക്കുചെയ്യുകയോ ഫോണിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോചെയ്യുക."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"സ്‌ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ പാസ്‌വേഡ് ടൈപ്പുചെയ്‌തെങ്കിൽ ടാബ്‌ലെറ്റ് ലോക്കുചെയ്യുകയോ ഈ എല്ലാ ഉപയോക്തൃവിവരവും മായ്‌ക്കുകയോ ചെയ്യുക."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"സ്‌ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android ടിവി ലോക്ക് ചെയ്യുകയോ ഈ ഉപയോക്തൃ ഡാറ്റയെല്ലാം മായ്‌ക്കുകയോ ചെയ്യുക."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"സ്‌ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android TV ലോക്ക് ചെയ്യുകയോ ഈ ഉപയോക്തൃ ഡാറ്റയെല്ലാം മായ്‌ക്കുകയോ ചെയ്യുക."</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"സ്‌ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ പാസ്‌വേഡ് ടൈപ്പുചെയ്‌തെങ്കിൽ ഫോൺ ലോക്കുചെയ്യുകയോ ഈ എല്ലാ ഉപയോക്തൃവിവരവും മായ്‌ക്കുകയോ ചെയ്യുക."</string>
<string name="policylab_resetPassword" msgid="214556238645096520">"സ്‌ക്രീൻ ലോക്ക് മാറ്റുക"</string>
<string name="policydesc_resetPassword" msgid="4626419138439341851">"സ്‌ക്രീൻ ലോക്ക് മാറ്റുക."</string>
@@ -684,7 +684,7 @@
<string name="policydesc_forceLock" msgid="1008844760853899693">"സ്‌ക്രീൻ ലോക്കുകൾ എങ്ങനെ വേണമെന്നും എപ്പോൾ വേണമെന്നും എന്നത് നിയന്ത്രിക്കുക"</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"എല്ലാ ഡാറ്റയും മായ്ക്കുക"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ഒരു ഫാക്‌ടറി ഡാറ്റ പുനഃസജ്ജീകരണം നടപ്പിലാക്കുന്നതിലൂടെ ടാബ്‌ലെറ്റിന്റെ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്‌ക്കുക."</string>
- <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ഫാക്‌ടറി ഡാറ്റ റീസെറ്റ് ചെയ്‌ത് നിങ്ങളുടെ Android ടിവിയിലെ ഉപകരണ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്‌ക്കുക."</string>
+ <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ഫാക്‌ടറി ഡാറ്റ റീസെറ്റ് ചെയ്‌ത് നിങ്ങളുടെ Android TV-യിലെ ഉപകരണ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്‌ക്കുക."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ഒരു ഫാക്‌ടറി ഡാറ്റ പുനഃസജ്ജീകരണം നടപ്പിലാക്കുന്നതിലൂടെ ഫോണിന്റെ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്‌ക്കുക."</string>
<string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ഉപയോക്തൃ ഡാറ്റ മായ്‌ക്കുക"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"മുന്നറിയിപ്പൊന്നും നൽകാതെ ഈ ടാബ്‌ലെറ്റിലെ ഈ ഉപയോക്താവിന്റെ ഡാറ്റ മായ്‌ക്കുക."</string>
@@ -838,7 +838,7 @@
<string name="faceunlock_multiple_failures" msgid="681991538434031708">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ശ്രമങ്ങളുടെ പരമാവധി കഴിഞ്ഞു"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"സിം കാർഡില്ല"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ടാബ്‌ലെറ്റിൽ സിം കാർഡൊന്നുമില്ല."</string>
- <string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"നിങ്ങളുടെ Android ടിവിയിൽ സിം കാർഡില്ല."</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"നിങ്ങളുടെ Android TV-യിൽ സിം കാർഡില്ല."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="1408695081255172556">"ഫോണിൽ സിം കാർഡൊന്നുമില്ല."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8473601862688263903">"ഒരു സിം കാർഡ് ചേർക്കുക."</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="3664999892038416334">"സിം കാർഡ് കാണുന്നില്ല അല്ലെങ്കിൽ റീഡുചെയ്യാനായില്ല. ഒരു സിം കാർഡ് ചേർക്കുക."</string>
@@ -864,10 +864,10 @@
<string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ Google സൈൻ ഇൻ ഉപയോഗിച്ച് നിങ്ങളുടെ Android ടിവി അൺലോക്ക് ചെയ്യാൻ ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിന് ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"നിങ്ങൾ അൺലോക്കുചെയ്യൽ പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> തെറ്റായ ശ്രമങ്ങൾക്കുശേഷം, Google സൈൻ ഇൻ ചെയ്യൽ ഉപയോഗിച്ച് നിങ്ങളുടെ ഫോൺ അൺലോക്കുചെയ്യുന്നതിന് ആവശ്യപ്പടും. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിനുള്ളിൽ വീണ്ടും ശ്രമിക്കുക."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"നിങ്ങൾ ഫോൺ അൺലോക്കുചെയ്യാൻ തവണ <xliff:g id="NUMBER_0">%1$d</xliff:g> തെറ്റായി ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ടാബ്‌ലെറ്റ് ഫാക്‌ടറി സ്ഥിരമായതിലേക്ക് പുനഃസജ്ജികരിക്കുകയും ഉപയോക്തൃ ഡാറ്റയെല്ലാം നഷ്‌ടപ്പെടുകയും ചെയ്യും."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി Android ടിവി അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, നിങ്ങളുടെ Android ടിവി ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് റീസെറ്റ് ചെയ്യപ്പെടുകയും എല്ലാ ഉപയോക്തൃ ഡാറ്റയും നഷ്‌ടപ്പെടുകയും ചെയ്യും."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി Android TV അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, നിങ്ങളുടെ Android TV ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് റീസെറ്റ് ചെയ്യപ്പെടുകയും എല്ലാ ഉപയോക്തൃ ഡാറ്റയും നഷ്‌ടപ്പെടുകയും ചെയ്യും."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ ഫോൺ അൺലോക്കുചെയ്യാൻ തെറ്റായി ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെടുകയാണെങ്കിൽ, ഫോൺ ഫാക്‌ടറി സ്ഥിരമായതിലേക്ക് പുനഃസജ്ജികരിക്കുകയും ഉപയോക്തൃ ഡാറ്റയെല്ലാം നഷ്‌ടപ്പെടുകയും ചെയ്യും."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ ടാബ്‌ലെറ്റ് അൺലോക്കുചെയ്യാൻ തെറ്റായി ശ്രമിച്ചു. ടാബ്‌ലെറ്റ് ഇപ്പോൾ ഫാക്‌ടറി സ്ഥിരമായതിലേക്ക് പുനസജ്ജീകരിക്കും."</string>
- <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി Android ടിവി അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. നിങ്ങളുടെ Android ടിവി ഇപ്പോൾ ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് റീസെറ്റ് ചെയ്യപ്പെടും."</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി Android TV അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. നിങ്ങളുടെ Android TV ഇപ്പോൾ ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് റീസെറ്റ് ചെയ്യപ്പെടും."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ ഫോൺ അൺലോക്കുചെയ്യാൻ തെറ്റായി ശ്രമിച്ചു. ഫോൺ ഇപ്പോൾ ഫാക്‌ടറി സ്ഥിരമായതിലേക്ക് പുനസജ്ജീകരിക്കും."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> നിമിഷത്തിനുള്ളിൽ വീണ്ടും ശ്രമിക്കുക."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"പാറ്റേൺ മറന്നോ?"</string>
@@ -954,7 +954,7 @@
<string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"ബ്രൗസർ സന്ദർശിച്ച എല്ലാ URL-കളുടെയും ചരിത്രവും ബ്രൗസറിന്റെ എല്ലാ ബുക്ക്‌മാർക്കുകളും റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ശ്രദ്ധിക്കുക: ഈ അനുമതി മൂന്നാം കക്ഷി ബ്രൗസറുകളോ വെബ് ബ്രൗസിംഗ് കഴിവുകളുള്ള മറ്റ് അപ്ലിക്കേഷനുകളോ നടപ്പിലാക്കാനിടയില്ല."</string>
<string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"വെബ് ബുക്ക്‌മാർക്കുകളും ചരിത്രവും റൈറ്റുചെയ്യുക"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ സംഭരിച്ചിരിക്കുന്ന ബ്രൗസറിന്റെ ചരിത്രമോ ബുക്ക്‌മാർക്കുകളോ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് ബ്രൗസർ ഡാറ്റ മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്. ശ്രദ്ധിക്കുക: ഈ അനുമതി മൂന്നാം കക്ഷി ബ്രൗസറുകളോ വെബ് ബ്രൗസിംഗ് കഴിവുകളുള്ള മറ്റ് അപ്ലിക്കേഷനുകളോ നടപ്പിലാക്കാനിടയില്ല."</string>
- <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"നിങ്ങളുടെ Android ടിവിയിൽ സംഭരിച്ചിരിക്കുന്ന ബ്രൗസറിന്റെ ചരിത്രവും ബുക്ക്‌മാർക്കുകളും പരിഷ്‌ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. ബ്രൗസർ ഡാറ്റ മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ ഇത് ആപ്പിനെ അനുവദിച്ചേക്കാം. ശ്രദ്ധിക്കുക: മൂന്നാം കക്ഷി ബ്രൗസറുകൾക്കോ വെബ് ബ്രൗസിംഗ് ശേഷികളുള്ള മറ്റ് ആപ്പുകൾക്കോ ഈ അനുമതി നടപ്പിലാക്കാനായേക്കില്ല."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"നിങ്ങളുടെ Android TV-യിൽ സംഭരിച്ചിരിക്കുന്ന ബ്രൗസറിന്റെ ചരിത്രവും ബുക്ക്‌മാർക്കുകളും പരിഷ്‌ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. ബ്രൗസർ ഡാറ്റ മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ ഇത് ആപ്പിനെ അനുവദിച്ചേക്കാം. ശ്രദ്ധിക്കുക: മൂന്നാം കക്ഷി ബ്രൗസറുകൾക്കോ വെബ് ബ്രൗസിംഗ് ശേഷികളുള്ള മറ്റ് ആപ്പുകൾക്കോ ഈ അനുമതി നടപ്പിലാക്കാനായേക്കില്ല."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"നിങ്ങളുടെ ഫോണിൽ സംഭരിച്ചിരിക്കുന്ന ബ്രൗസറിന്റെ ചരിത്രമോ ബുക്ക്‌മാർക്കുകളോ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് ബ്രൗസർ ഡാറ്റ മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്. ശ്രദ്ധിക്കുക: ഈ അനുമതി മൂന്നാം കക്ഷി ബ്രൗസറുകളോ വെബ് ബ്രൗസിംഗ് കഴിവുകളുള്ള മറ്റ് അപ്ലിക്കേഷനുകളോ നടപ്പിലാക്കാനിടയില്ല."</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"ഒരു അലാറം സജ്ജീകരിക്കുക"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"ഒരു ഇൻസ്റ്റാളുചെയ്‌ത അലാറം ക്ലോക്ക് അപ്ലിക്കേഷനിൽ അലാറം സജ്ജീകരിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ചില അലാറം ക്ലോക്ക് അപ്ലിക്കേഷനുകൾ ഈ സവിശേഷത നടപ്പിലാക്കാതിരുന്നേക്കാം."</string>
@@ -1309,7 +1309,7 @@
<string name="adb_active_notification_title" msgid="408390247354560331">"USB ഡീബഗ്ഗിംഗ് കണക്റ്റ് ചെയ്തു"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"USB ഡീബഗ്ഗിംഗ് ഓഫാക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB ഡീബഗ്ഗുചെയ്യൽ പ്രവർത്തനരഹിതമാക്കാൻ തിരഞ്ഞെടുക്കുക."</string>
- <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"വയർലെസ് ഡീബഗ്ഗിംഗ് കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"വയർലെസ് ഡീബഗ്ഗിംഗ് കണക്റ്റ് ചെയ്തു"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"വയർലെസ് ഡീബഗ്ഗിംഗ് ഓഫാക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"വയർലെസ് ഡീബഗ്ഗിംഗ് പ്രവർത്തനരഹിതമാക്കാൻ തിരഞ്ഞെടുക്കുക."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"പരിശോധനാ സംവിധാനങ്ങൾ മോഡ് പ്രവർത്തനക്ഷമമാക്കി"</string>
@@ -1612,19 +1612,18 @@
<string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി Android ടിവി അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, നിങ്ങളുടെ Android ടിവി ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് റീസെറ്റ് ചെയ്യപ്പെടുകയും എല്ലാ ഉപയോക്തൃ ഡാറ്റയും നഷ്‌ടപ്പെടുകയും ചെയ്യും."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"നിങ്ങൾ ഫോൺ അൺലോക്കുചെയ്യാൻ തവണ <xliff:g id="NUMBER_0">%1$d</xliff:g> തെറ്റായി ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ഫോൺ ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് പുനഃസജ്ജികരിക്കുകയും ഉപയോക്തൃ ഡാറ്റയെല്ലാം നഷ്‌ടപ്പെടുകയും ചെയ്യും."</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"നിങ്ങൾ ടാബ്‌ലെറ്റ് അൺലോക്കുചെയ്യാൻ തവണ <xliff:g id="NUMBER">%d</xliff:g> തെറ്റായി ശ്രമിച്ചു. ടാബ്‌ലെറ്റ് ഇപ്പോൾ ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് പുനസജ്ജീകരിക്കും."</string>
- <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി Android ടിവി അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. നിങ്ങളുടെ Android ടിവി ഇപ്പോൾ ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് റീസെറ്റ് ചെയ്യപ്പെടും."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി Android TV അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. നിങ്ങളുടെ Android TV ഇപ്പോൾ ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് റീസെറ്റ് ചെയ്യപ്പെടും."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"നിങ്ങൾ ഫോൺ അൺലോക്കുചെയ്യാൻ തവണ <xliff:g id="NUMBER">%d</xliff:g> തെറ്റായി ശ്രമിച്ചു. ഫോൺ ഇപ്പോൾ ഫാക്‌ടറി ഡിഫോൾട്ടിലേക്ക് പുനസജ്ജീകരിക്കും."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ഒരു ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിനുള്ള വീണ്ടും ശ്രമിക്കുക."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് നിങ്ങളുടെ Android ടിവി അൺലോക്ക് ചെയ്യാൻ ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിന് ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് നിങ്ങളുടെ Android TV അൺലോക്ക് ചെയ്യാൻ ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിന് ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ഒരു ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് ഫോൺ അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിനുള്ള വീണ്ടും ശ്രമിക്കുക."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"നീക്കംചെയ്യുക"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> എന്നതിൽ നിന്നുള്ള പശ്ചാത്തലത്തിൽ ആരംഭിച്ച് ഫോർഗ്രൗണ്ടിൽ വരുന്ന സേവനത്തിന് ഭാവി R ബിൽഡുകളിൽ, \'ഉപയോഗിക്കുമ്പോൾ മാത്രമുള്ള അനുമതി\' ഉണ്ടായിരിക്കില്ല. go/r-bg-fgs-restriction കണ്ട് ബഗ് റിപ്പോർട്ട് ഫയൽ ചെയ്യുക."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"മുകളിൽക്കൊടുത്തിരിക്കുന്ന ശുപാർശചെയ്‌ത ലെവലിലേക്ക് വോളിയം വർദ്ധിപ്പിക്കണോ?\n\nഉയർന്ന വോളിയത്തിൽ ദീർഘനേരം കേൾക്കുന്നത് നിങ്ങളുടെ ശ്രവണ ശേഷിയെ ദോഷകരമായി ബാധിക്കാം."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ഉപയോഗസഹായി കുറുക്കുവഴി ഉപയോഗിക്കണോ?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"കുറുക്കുവഴി ഓണായിരിക്കുമ്പോൾ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ഉപയോഗസഹായി ഫീച്ചറുകൾ ഓണാക്കണോ?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത്, ഉപയോഗസഹായി ഫീച്ചറുകൾ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന വിധം ഇത് മാറ്റിയേക്കാം.\n\nനിലവിലുള്ള ഫീച്ചറുകൾ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nതിരഞ്ഞെടുത്ത ഫീച്ചറുകൾ ക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിൽ മാറ്റാനാവും."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത്, ഉപയോഗസഹായി ഫീച്ചറുകൾ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന രീതിയെ ഇത് മാറ്റിയേക്കാം.\n\nനിലവിലുള്ള ഫീച്ചറുകൾ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nതിരഞ്ഞെടുത്ത ഫീച്ചറുകൾ ക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിൽ മാറ്റാനാവും."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> ഓണാക്കണോ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത് ഉപയോഗസഹായി ഫീച്ചറായ <xliff:g id="SERVICE">%1$s</xliff:g> എന്നതിനെ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന വിധം ഇത് മാറ്റിയേക്കാം.\n\nക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിലെ മറ്റൊരു ഫീച്ചറിലേക്ക് നിങ്ങൾക്ക് ഈ കുറുക്കുവഴി മാറ്റാനാവും."</string>
@@ -1641,9 +1640,9 @@
<string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"ഇതിന് ഒരു ആപ്പുമായോ ഹാർഡ്‌വെയർ സെൻസറുമായോ ഉള്ള നിങ്ങളുടെ ആശയവിനിമയങ്ങൾ ട്രാക്ക് ചെയ്യാനും നിങ്ങളുടെ പേരിൽ ആശയവിനിമയം നടത്താനും കഴിയും."</string>
<string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"അനുവദിക്കൂ"</string>
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"നിരസിക്കുക"</string>
- <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ഇത് ഉപയോഗിക്കാൻ ആരംഭിക്കുന്നതിന് ഫീച്ചർ ടാപ്പ് ചെയ്യുക:"</string>
+ <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ഉപയോഗിച്ച് തുടങ്ങാൻ ഫീച്ചർ ടാപ്പ് ചെയ്യുക:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ഉപയോഗസഹായി ബട്ടണിന്റെ സഹായത്തോടെ, ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"വോളിയം കീ കുറുക്കുവഴിയുടെ സഹായത്തോടെ, ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"വോളിയം കീ കുറുക്കുവഴിയിലൂടെ ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ഓഫാക്കിയിരിക്കുന്നു"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"കുറുക്കുവഴികൾ തിരുത്തുക"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"പൂർത്തിയാക്കി"</string>
@@ -1652,7 +1651,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"വർണ്ണ വിപര്യയം"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"നിറം ക്രമീകരിക്കൽ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ അമർത്തിപ്പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഉപയോഗിക്കാൻ, രണ്ട് വോളിയം കീകളും മൂന്ന് സെക്കൻഡ് അമർത്തിപ്പിടിക്കുക"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"നിങ്ങൾ ഉപയോഗസഹായി ബട്ടൺ ടാപ്പ് ചെയ്യുമ്പോൾ ഉപയോഗിക്കുന്നതിന് ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ഉപയോഗസഹായി വിരൽചലനത്തോടൊപ്പം ഉപയോഗിക്കാൻ ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക (രണ്ട് വിരലുകളുപയോഗിച്ച് സ്‌ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക):"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 11683ae46138..121b71c1b4a7 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -175,7 +175,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"Хэт олон <xliff:g id="CONTENT_TYPE">%s</xliff:g>-г устгах оролдлого хийсэн байна."</string>
<string name="low_memory" product="tablet" msgid="5557552311566179924">"Таблетийн сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
<string name="low_memory" product="watch" msgid="3479447988234030194">"Цагны сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
- <string name="low_memory" product="tv" msgid="6663680413790323318">"Android TВ төхөөрөмжийн хадгалах сан дүүрсэн байна. Зай гаргахын тулд зарим файлыг устгана уу."</string>
+ <string name="low_memory" product="tv" msgid="6663680413790323318">"Android TV төхөөрөмжийн хадгалах сан дүүрсэн байна. Зай гаргахын тулд зарим файлыг устгана уу."</string>
<string name="low_memory" product="default" msgid="2539532364144025569">"Утасны сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
<item quantity="other">Сертификатын эрхийг суулгасан</item>
@@ -206,7 +206,7 @@
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Асаах"</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>
+ <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-н сонголт"</string>
<string name="power_dialog" product="default" msgid="1107775420270203046">"Утасны сонголт"</string>
<string name="silent_mode" msgid="8796112363642579333">"Дуугүй горим"</string>
<string name="turn_on_radio" msgid="2961717788170634233">"Утасгүй холбоог асаах"</string>
@@ -224,7 +224,7 @@
<string name="reboot_to_reset_message" msgid="3347690497972074356">"Дахин эхэлж байна..."</string>
<string name="shutdown_progress" msgid="5017145516412657345">"Унтрааж байна…"</string>
<string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"Таны таблет унтрах болно."</string>
- <string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"Таны Android ТВ төхөөрөмж унтарна."</string>
+ <string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"Таны Android TV төхөөрөмж унтарна."</string>
<string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"Таны цаг унтрах болно."</string>
<string name="shutdown_confirm" product="default" msgid="136816458966692315">"Таны утас унтрах болно."</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"Та унтраах уу?"</string>
@@ -233,7 +233,7 @@
<string name="recent_tasks_title" msgid="8183172372995396653">"Сүүлийн"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"Сүүлийн апп хоосон."</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"Таблет сонголт"</string>
- <string name="global_actions" product="tv" msgid="3871763739487450369">"Android ТВ-н сонголт"</string>
+ <string name="global_actions" product="tv" msgid="3871763739487450369">"Android TV-н сонголт"</string>
<string name="global_actions" product="default" msgid="6410072189971495460">"Утасны сонголтууд"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Дэлгэцний түгжээ"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Унтраах"</string>
@@ -357,7 +357,7 @@
<string name="permdesc_sendSms" msgid="6757089798435130769">"Апп нь SMS мессеж илгээх боломжтой. Энэ нь санаандгүй төлбөрт оруулж болзошгүй. Хортой апп нь таны зөвшөөрөлгүйгээр мессеж илгээн таныг төлбөрт оруулж болзошгүй."</string>
<string name="permlab_readSms" msgid="5164176626258800297">"таны текст мессежийг унших(SMS эсвэл MMS)"</string>
<string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"Энэ апп таны таблетад хадгалсан бүх SMS (текст) зурвасыг унших боломжтой."</string>
- <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"Энэ апп таны Android ТВ төхөөрөмжид хадгалсан бүх SMS (текст) мессежийг уншиж чадна."</string>
+ <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"Энэ апп таны Android TV төхөөрөмжид хадгалсан бүх SMS (текст) мессежийг уншиж чадна."</string>
<string name="permdesc_readSms" product="default" msgid="774753371111699782">"Энэ апп таны утсанд хадгалсан бүх SMS (текст) зурвасыг унших боломжтой."</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"текст мессеж(WAP) хүлээн авах"</string>
<string name="permdesc_receiveWapPush" msgid="1638677888301778457">"Апп нь WAP мессежийг хүлээн авах болон биелүүлэх боломжтой. Энэ зөвшөөрөл нь танд илгээсэн мессежийг танд харуулалгүйгээр хянах эсвэл устгах боломжийг агуулна."</string>
@@ -379,7 +379,7 @@
<string name="permdesc_useDataInBackground" msgid="1230753883865891987">"Энэ апп цаана ажиллах боломжтой. Энэ нь датаны хэрэглээг нэмэгдүүлж болзошгүй."</string>
<string name="permlab_persistentActivity" msgid="464970041740567970">"апп-г байнга ажиллуулах"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"Апп нь өөрийн хэсгийн санах ойд байнга байлгах боломжтой. Энэ нь бусад апп-уудын ашиглах санах ойг хязгаарлан таблетыг удаашруулах болно."</string>
- <string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"Аппад өөрийн хэсгийг санах ойд тогтмол хадгалахыг зөвшөөрнө. Энэ нь таны Android ТВ төхөөрөмжийг удаашруулж буй бусад аппад боломжтой санах ойг хязгаарлаж болно."</string>
+ <string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"Аппад өөрийн хэсгийг санах ойд тогтмол хадгалахыг зөвшөөрнө. Энэ нь таны Android TV төхөөрөмжийг удаашруулж буй бусад аппад боломжтой санах ойг хязгаарлаж болно."</string>
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Апп нь өөрийн хэсгийг санах ойд байнга байлгах боломжтой. Энэ нь бусад апп-уудын ашиглах санах ойг хязгаарлан утсыг удаашруулах болно."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"интерактив (foreground) үйлчилгээг ажиллуулах"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Аппад интерактив (foreground) үйлчилгээг ашиглахыг зөвшөөрнө үү."</string>
@@ -389,35 +389,35 @@
<string name="permdesc_writeSettings" msgid="8293047411196067188">"Апп нь системийн тохиргооны датаг өөрчлөх боломжтой. Хортой апп нь таны системийн тохиргоог сүйтгэх боломжтой."</string>
<string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"Эхлэхэд ажиллуулах"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"Апп нь систем асаж дуусахад шууд өөрийгөө асаах боломжтой. Ингэснээр таблетыг асахад их хугацаа орох болон байнга ажилладаг апп нь таблетийг бүхэлд нь удаашруулах боломжтой."</string>
- <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Аппад системийг ачаалж дуусмагц өөрийгөө эхлүүлэхийг зөвшөөрнө. Энэ нь таны Android ТВ төхөөрөмжийн эхлэх хугацааг удаашруулах боломжтойгоос гадна аппыг тогтмол ажиллуулснаар төхөөрөмжийн ерөнхий хурдыг удаашруулж болзошгүй."</string>
+ <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Аппад системийг ачаалж дуусмагц өөрийгөө эхлүүлэхийг зөвшөөрнө. Энэ нь таны Android TV төхөөрөмжийн эхлэх хугацааг удаашруулах боломжтойгоос гадна аппыг тогтмол ажиллуулснаар төхөөрөмжийн ерөнхий хурдыг удаашруулж болзошгүй."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"Апп нь систем асаж дуусахад шууд өөрийгөө асаах боломжтой. Ингэснээр утсыг асахад их хугацаа орох болон байнга ажилладаг апп нь утсыг бүхэлд нь удаашруулах боломжтой."</string>
<string name="permlab_broadcastSticky" msgid="4552241916400572230">"тасардаггүй өргөн дамжууллыг илгээх"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"Апп нь өргөн дамжуулал дууссаны дараа үлдсэн өргөн дамжуулалыг илгээх боломжтой. Ихээр ашиглах нь хэт их санах ой ашиглан таблетыг удаашруулах болон тогтворгүй болгох боломжтой."</string>
- <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Аппад нэвтрүүлэг дууссаны дараа үлдэх бэхлэгдсэн нэвтрүүлэг илгээхийг зөвшөөрнө. Хэт их ашиглах нь санах ойн ачааллыг нэмэгдүүлж, улмаар таны Android ТВ төхөөрөмжийг удаан эсвэл тогтворгүй болгож болзошгүй."</string>
+ <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Аппад нэвтрүүлэг дууссаны дараа үлдэх бэхлэгдсэн нэвтрүүлэг илгээхийг зөвшөөрнө. Хэт их ашиглах нь санах ойн ачааллыг нэмэгдүүлж, улмаар таны Android TV төхөөрөмжийг удаан эсвэл тогтворгүй болгож болзошгүй."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Апп нь өргөн дамжуулал дууссаны дараа үлдсэн өргөн дамжуулалыг илгээх боломжтой. Ихээр ашиглах нь хэт их санах ой ашиглан утсыг удаашруулах болон тогтворгүй болгох боломжтой."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"өөрийн харилцагчдыг унших"</string>
<string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Аппaд таны таблет дээр хадгалагдсан харилцагчдын өгөгдлийг уншихыг зөвшөөрнө. Мөн аппууд нь таны таблет дээрх харилцагч үүсгэсэн бүртгэлд хандах боломжтой байна. Үүнд таны суулгасан аппуудын үүсгэсэн бүртгэлийг оролцуулж болзошгүй. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд нь танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг хуваалцаж болзошгүй."</string>
- <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Аппaд таны Android TВ төхөөрөмж дээр хадгалагдсан харилцагчдын өгөгдлийг уншихыг зөвшөөрнө. Мөн аппууд нь таны Android TВ төхөөрөмж дээрх харилцагч үүсгэсэн бүртгэлд хандах боломжтой байна. Үүнд таны суулгасан аппуудын үүсгэсэн бүртгэлийг оролцуулж болзошгүй. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд нь танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг хуваалцаж болзошгүй."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Аппaд таны Android TV төхөөрөмж дээр хадгалагдсан харилцагчдын өгөгдлийг уншихыг зөвшөөрнө. Мөн аппууд нь таны Android TV төхөөрөмж дээрх харилцагч үүсгэсэн бүртгэлд хандах боломжтой байна. Үүнд таны суулгасан аппуудын үүсгэсэн бүртгэлийг оролцуулж болзошгүй. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд нь танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг хуваалцаж болзошгүй."</string>
<string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Аппaд таны утсан дээр хадгалагдсан харилцагчдын өгөгдлийг уншихыг зөвшөөрнө. Мөн аппууд нь таны утсан дээрх харилцагч үүсгэсэн бүртгэлд хандах боломжтой байна. Үүнд таны суулгасан аппуудын үүсгэсэн бүртгэлийг оролцуулж болзошгүй. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд нь танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг хуваалцаж болзошгүй."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"таны харилцагчдыг өөрчлөх"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Аппад таны таблет дээр хадгалагдсан харилцагчдын өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь харилцагчийн өгөгдлийг устгахыг аппуудад зөвшөөрнө."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Аппaд таны Android TВ төхөөрөмж дээр хадгалагдсан харилцагчдын өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь харилцагчийн өгөгдлийг устгахыг аппуудад зөвшөөрнө."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Аппaд таны Android TV төхөөрөмж дээр хадгалагдсан харилцагчдын өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь харилцагчийн өгөгдлийг устгахыг аппуудад зөвшөөрнө."</string>
<string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Аппад таны утсан дээр хадгалагдсан харилцагчдын өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь харилцагчийн өгөгдлийг устгахыг аппуудад зөвшөөрнө."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"дуудлагын логийг унших"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Энэ апп таны дуудлагын түүхийг унших боломжтой."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"дуудлагын логруу бичих"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Апп нь таны таблетын ирсэн гарсан дуудлага зэргийг агуулсан дуудлагын логыг унших боломжтой. Хортой апп нь энийг ашиглан таны дуудлагын логыг өөрчлөх болон арилгах боломжтой."</string>
- <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Аппад таны Android ТВ төхөөрөмжийн ирсэн болон залгасан дуудлага зэрэг өгөгдөл бүхий дуудлагын жагсаалтыг өөрчлөхийг зөвшөөрнө. Хортой аппууд үүнийг ашиглан таны дуудлагын жагсаалтыг устгаж эсвэл өөрчилж болзошгүй."</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Аппад таны Android TV төхөөрөмжийн ирсэн болон залгасан дуудлага зэрэг өгөгдөл бүхий дуудлагын жагсаалтыг өөрчлөхийг зөвшөөрнө. Хортой аппууд үүнийг ашиглан таны дуудлагын жагсаалтыг устгаж эсвэл өөрчилж болзошгүй."</string>
<string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Апп нь таны утасны ирсэн гарсан дуудлага зэргийг агуулсан дуудлагын логыг өөрчлөх боломжтой. Хортой апп нь энийг ашиглан таны дуудлагын логыг өөрчлөх болон арилгах боломжтой."</string>
<string name="permlab_bodySensors" msgid="3411035315357380862">"биеийн мэдрэгчид хандах (зүрхний хэмнэл шалгагч г.м)"</string>
<string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"Апп-т таны зүрхний цохилт гэх мэт биеийн байдлыг хянадаг мэдрэгчдийн датанд хандалт хийх боломж олгоно."</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"Хуанлийн арга хэмжээ, дэлгэрэнгүйг унших"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Энэ апп таны таблетад хадгалсан хуанлийн бүх арга хэмжээг унших, хуанлийн өгөгдлийг хуваалцах, хадгалах боломжтой."</string>
- <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Энэ апп таны Android ТВ төхөөрөмжид хадгалсан календарийн бүх арга хэмжээг унших болон таны календарийн өгөгдлийг хуваалцах эсвэл хадгалах боломжтой."</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Энэ апп таны Android TV төхөөрөмжид хадгалсан календарийн бүх арга хэмжээг унших болон таны календарийн өгөгдлийг хуваалцах эсвэл хадгалах боломжтой."</string>
<string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"Энэ апп таны утсанд хадгалсан хуанлийн бүх арга хэмжээг унших, хуанлийн өгөгдлийг хуваалцах, хадгалах боломжтой."</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"календарын хуваарийг нэмэх эсвэл өөрчлөх болон эзэмшигчид мэдэгдэлгүйгээр зочидруу имэйл илгээх"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"Энэ апп таны таблет дээр хуанлийн арга хэмжээг нэмэх, устгах, эсвэл өөрчлөх боломжтой. Энэ апп нь хуанли эзэмшигчээс зурвас илгээсэн мэт харагдах, эсвэл эзэмшигчид мэдэгдэлгүйгээр арга хэмжээг өөрчлөх боломжтой."</string>
- <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"Энэ апп таны Android ТВ төхөөрөмжид календарийн арга хэмжээ нэмэх, үүнийг устгах, эсвэл өөрчлөх боломжтой. Энэ апп календарийн өмчлөгчөөс ирсэн мэт харагдаж болох мессеж илгээх эсвэл арга хэмжээг өмчлөгчид нь мэдэгдэлгүйгээр өөрчлөх боломжтой."</string>
+ <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"Энэ апп таны Android TV төхөөрөмжид календарийн арга хэмжээ нэмэх, үүнийг устгах, эсвэл өөрчлөх боломжтой. Энэ апп календарийн өмчлөгчөөс ирсэн мэт харагдаж болох мессеж илгээх эсвэл арга хэмжээг өмчлөгчид нь мэдэгдэлгүйгээр өөрчлөх боломжтой."</string>
<string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Энэ апп таны утсанд хуанлийн арга хэмжээг нэмэх, устгах, эсвэл өөрчлөх боломжтой. Энэ апп нь хуанли эзэмшигчээс зурвас илгээсэн мэт харагдах, эсвэл эзэмшигчид мэдэгдэлгүйгээр арга хэмжээг өөрчлөх боломжтой."</string>
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"байршил нийлүүлэгчийн нэмэлт тушаалд хандах"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Апп нь байршил нийлүүлэгчийн нэмэлт тушаалд хандах боломжтой. Энэ нь апп-д GPS эсвэл бусад байршлын үйлчилгээний ажиллагаанд нөлөөлөх боломжийг олгоно."</string>
@@ -462,15 +462,15 @@
<string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"Төхөөрөмжийн утасны дугаарт хандах зөвшөөрлийг апп-д олгоно."</string>
<string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"машины дэлгэцийг асаалттай байлгах"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1527660973931694000">"таблетыг унтуулахгүй байлгах"</string>
- <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"таны Android TВ төхөөрөмжийг идэвхгүй болохоос сэргийлэх"</string>
+ <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"таны Android TV төхөөрөмжийг идэвхгүй болохоос сэргийлэх"</string>
<string name="permlab_wakeLock" product="default" msgid="569409726861695115">"утсыг унтуулахгүй байлгах"</string>
<string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"Аппад машины дэлгэцийг асаалттай байлгахыг зөвшөөрдөг."</string>
<string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"Апп нь таблетыг унтахаас сэргийлэх боломжтой"</string>
- <string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Аппад таны Android ТВ төхөөрөмжийг идэвхгүй болохоос сэргийлэхийг зөвшөөрнө."</string>
+ <string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Аппад таны Android TV төхөөрөмжийг идэвхгүй болохоос сэргийлэхийг зөвшөөрнө."</string>
<string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"Апп нь утсыг унтахаас сэргийлэх боломжтой"</string>
<string name="permlab_transmitIr" msgid="8077196086358004010">"хэт улаанаар дамжуулах"</string>
<string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Апп-д таблетын хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string>
- <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Аппад таны Android ТВ төхөөрөмжийн хэт улаан туяаны дамжуулагчийг ашиглахыг зөвшөөрнө."</string>
+ <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Аппад таны Android TV төхөөрөмжийн хэт улаан туяаны дамжуулагчийг ашиглахыг зөвшөөрнө."</string>
<string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Апп-д утасны хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string>
<string name="permlab_setWallpaper" msgid="6959514622698794511">"ханын зургийг тохируулах"</string>
<string name="permdesc_setWallpaper" msgid="2973996714129021397">"Апп нь системийн ханын зургийг тохируулах боломжтой."</string>
@@ -478,11 +478,11 @@
<string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Апп нь системийн ханын зургийн хэмжээний саналыг тохируулах боломжтой"</string>
<string name="permlab_setTimeZone" msgid="7922618798611542432">"цагийн бүсийн тохиргоо"</string>
<string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Апп нь таблетын цагийн бүсийг солих боломжтой."</string>
- <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Аппад таны Android ТВ төхөөрөмжийн цагийн бүсийг өөрчлөхийг зөвшөөрнө."</string>
+ <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Аппад таны Android TV төхөөрөмжийн цагийн бүсийг өөрчлөхийг зөвшөөрнө."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"Апп нь утасны цагийн бүсийг өөрчлөх боломжтой."</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"төхөөрөмж дээрх акаунтыг олох"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Апп нь таблетэд мэдэгдэж байгаа бүртгэлийн жагсаалтыг авах боломжтой. Энд таны суулгасан аппликейшнүүдийг үүсгэсэн бүх акаунтууд хамрагдана."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Аппад таны Android ТВ төхөөрөмжөөр танигдсан бүртгэлийн жагсаалтыг авахыг зөвшөөрнө. Үүнд таны суулгасан аппуудын үүсгэсэн аливаа бүртгэлийг оруулж болзошгүй."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Аппад таны Android TV төхөөрөмжөөр танигдсан бүртгэлийн жагсаалтыг авахыг зөвшөөрнө. Үүнд таны суулгасан аппуудын үүсгэсэн аливаа бүртгэлийг оруулж болзошгүй."</string>
<string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Апп нь утсанд мэдэгдэж байгаа бүртгэлийн жагсаалтыг авах боломжтой. Энд таны суулгасан аппликейшнүүдийг үүсгэсэн бүх акаунтууд хамрагдана."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"сүлжээний холболтыг үзэх"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Апп нь сүлжээ байгаа болон холбогдсон эсэх зэрэг сүлжээний холболтын талаарх мэдээллийг харах боломжтой."</string>
@@ -498,21 +498,21 @@
<string name="permdesc_changeWifiState" msgid="7170350070554505384">"Апп нь Wi-Fi холболтын цэгтэй холбогдох буюу салах боломжтой ба тохируулсан Wi-Fi сүлжээнд өөрчлөлт хийх боломжтой."</string>
<string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"Wi-Fi олон дамжуулалт хүлээн авахыг зөвшөөрөх"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"Апп нь олон дамжуулал ашиглан Wi-Fi сүлжээн дэх бүх төхөөрөмжрүү пакет илгээх болон хүлээн авах боломжтой. Энэ нь олон дамжуулал ашиглахгүй горимоос илүү их тэжээл зарцуулна."</string>
- <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Аппад таны Android ТВ төхөөрөмжөөс гадна Wi-Fi сүлжээг ашиглаж буй бүх төхөөрөмжид илгээсэн багцыг олон цэгийн хаяг ашиглан хүлээн авахыг зөвшөөрнө. Энэ нь олон цэгийн бус горимоос илүү их тэжээл ашиглана."</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Аппад таны Android TV төхөөрөмжөөс гадна Wi-Fi сүлжээг ашиглаж буй бүх төхөөрөмжид илгээсэн багцыг олон цэгийн хаяг ашиглан хүлээн авахыг зөвшөөрнө. Энэ нь олон цэгийн бус горимоос илүү их тэжээл ашиглана."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"Апп нь олон дамжуулал ашиглан Wi-Fi сүлжээн дэх бүх төхөөрөмжрүү пакет илгээх болон хүлээн авах боломжтой. Энэ нь олон дамжуулал ашиглахгүй горимоос илүү их тэжээл зарцуулна."</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"Bluetooth тохиргоонд хандах"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Апп нь дотоод блютүүт таблетын тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой"</string>
- <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Аппад таны Android ТВ төхөөрөмжийн Bluetooth-г тохируулах болон алсын төхөөрөмжүүдийг илрүүлж, тэдгээртэй хослуулахыг зөвшөөрнө."</string>
+ <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Аппад таны Android TV төхөөрөмжийн Bluetooth-г тохируулах болон алсын төхөөрөмжүүдийг илрүүлж, тэдгээртэй хослуулахыг зөвшөөрнө."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Апп нь утасны дотоод блютүүтыг тохируулах боломжтой ба гадаад төхөөрөмжийг олох болон хос үүсгэх боломжтой."</string>
<string name="permlab_accessWimaxState" msgid="7029563339012437434">"WiMAX-д холбогдох болон салах"</string>
<string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Апп нь WiMAX идэвхтэй эсэх болон холбогдсон WiMAX сүлжээний талаар мэдээллийг тодорхойлох боломжтой."</string>
<string name="permlab_changeWimaxState" msgid="6223305780806267462">"WiMAX статусыг солих"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"Апп нь WiMAX сүлжээнд таблетыг холбох болон салгах боломжтой."</string>
- <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"Аппад таны Android ТВ төхөөрөмжид холбогдож, үүнийг WiMAX сүлжээнээс салгахыг зөвшөөрнө."</string>
+ <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"Аппад таны Android TV төхөөрөмжид холбогдож, үүнийг WiMAX сүлжээнээс салгахыг зөвшөөрнө."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"Апп нь WiMAX сүлжээнд утсыг холбох болон салгах боломжтой."</string>
<string name="permlab_bluetooth" msgid="586333280736937209">"Bluetooth төхөөрөмжтэй хос үүсгэх"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Апп нь таблет дээрх блютүүт тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
- <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Аппад таны Android ТВ төхөөрөмж дээрх Bluetooth-н тохируулгыг харах болон хослуулсан төхөөрөмжүүдтэй холболт хийж, холболтыг баталгаажуулахыг зөвшөөрнө."</string>
+ <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Аппад таны Android TV төхөөрөмж дээрх Bluetooth-н тохируулгыг харах болон хослуулсан төхөөрөмжүүдтэй холболт хийж, холболтыг баталгаажуулахыг зөвшөөрнө."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Апп нь утсан дээрх Bluetooth тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Сонгосон NFC төлбөрийн үйлчилгээний мэдээлэл"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Бүртгүүлсэн төхөөрөмж болон маршрутын хүрэх цэг зэрэг сонгосон nfc төлбөрийн үйлчилгээний мэдээллийг авахыг аппад зөвшөөрдөг."</string>
@@ -673,10 +673,10 @@
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Дэлгэц түгжих нууц үг болон ПИН кодны урт болон нийт тэмдэгтийн уртыг хянах."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Дэлгэцийн түгжээг тайлах оролдлогыг хянах"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал таблетыг түгжих болон таблетын бүх датаг арилгана"</string>
- <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android ТВ төхөөрөмжийг түгжиж эсвэл үүний бүх өгөгдлийг устгана."</string>
+ <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android TV төхөөрөмжийг түгжиж эсвэл үүний бүх өгөгдлийг устгана."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах, ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал утсыг түгжих болон утасны бүх датаг арилгана"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Дэлгэцийн түгжээг тайлахад оруулсан буруу нууц үгийн давтамжийг хянаж таблетыг түгжих эсвэл буруу нууц үгийг хэт олон удаа оруулсан тохиолдолд энэ хэрэглэгчийн мэдээллийг устгах."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android ТВ төхөөрөмжийг түгжиж эсвэл энэ хэрэглэгчийн бүх өгөгдлийг устгана."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android TV төхөөрөмжийг түгжиж эсвэл энэ хэрэглэгчийн бүх өгөгдлийг устгана."</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Дэлгэцийн түгжээг тайлахад оруулсан буруу нууц үгийн давтамжийг хянаж гар утсыг түгжих эсвэл буруу нууц үгийг хэт олон удаа оруулсан тохиолдолд энэ хэрэглэгчийн мэдээллийг устгах."</string>
<string name="policylab_resetPassword" msgid="214556238645096520">"Дэлгэцийн түгжээг өөрчлөх"</string>
<string name="policydesc_resetPassword" msgid="4626419138439341851">"Дэлгэцийн түгжээг өөрчлөх."</string>
@@ -684,11 +684,11 @@
<string name="policydesc_forceLock" msgid="1008844760853899693">"Дэлгэц хэзээ яаж түгжихийг удирдах"</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Бүх датаг арилгах"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Үйлдвэрийн дата утгыг өгсөнөөр таблетын дата шууд арилгагдана."</string>
- <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Таны Android ТВ төхөөрөмжийн өгөгдлийг танд анхааруулалгүйгээр үйлдвэрээс гарсан төлөвт шилжүүлэн устгана."</string>
+ <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Таны Android TV төхөөрөмжийн өгөгдлийг танд анхааруулалгүйгээр үйлдвэрээс гарсан төлөвт шилжүүлэн устгана."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Сануулахгүйгээр утасны бүх мэдээллийг устгаж, үйлдвэрийн өгөгдмөл байдалд шилжүүлнэ"</string>
<string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Хэрэглэгчийн мэдээллийг арилгах"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Анхааруулга өгөхгүйгээр энэ хэрэглэгчийн энэ таблет дээрх мэдээллийг устгах."</string>
- <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Энэ Android ТВ төхөөрөмж дээрх хэрэглэгчийн өгөгдлийг хэрэглэгчид анхааруулалгүйгээр устгана."</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Энэ Android TV төхөөрөмж дээрх хэрэглэгчийн өгөгдлийг хэрэглэгчид анхааруулалгүйгээр устгана."</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Анхааруулга өгөхгүйгээр энэ хэрэглэгчийн энэ гар утсан дээрх мэдээллийг устгах."</string>
<string name="policylab_setGlobalProxy" msgid="215332221188670221">"Төхөрөөмжийн глобал проксиг тохируулах"</string>
<string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Бодлогыг ашиглах боломжтой үед төхөөрөмжийн олон улсын эрхийг тохируулах. Зөвхөн төхөөрөмж эзэмшигч нь олон улсын эрхийг тохируулах боломжтой."</string>
@@ -838,7 +838,7 @@
<string name="faceunlock_multiple_failures" msgid="681991538434031708">"Нүүрээр түгжээ тайлах оролдлогын тоо дээд хэмжээнээс хэтэрсэн"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM карт байхгүй"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Таблет SIM картгүй."</string>
- <string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Таны Android ТВ төхөөрөмжид SIM карт алга."</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Таны Android TV төхөөрөмжид SIM карт алга."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="1408695081255172556">"Утсанд SIM карт байхгүй."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8473601862688263903">"SIM картыг оруулна уу."</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="3664999892038416334">"SIM карт байхгүй эсвэл унших боломжгүй. SIM карт оруулна уу."</string>
@@ -861,13 +861,13 @@
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"Та нууц үгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу бичив. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"Та PIN кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу бичив. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та таблетаа тайлахын тулд Google нэвтрэлтээ ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд Android ТВ төхөөрөмжийнхөө түгжээг тайлахын тулд Google-д нэвтрэх шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд Android TV төхөөрөмжийнхөө түгжээг тайлахын тулд Google-д нэвтрэх шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оролдвол, та таблетаа тайлахын тулд Google нэвтрэлтээ ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"Та таблетыг тайлах гэж <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдлоо. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оролдвол таблет үйлдвэрийн үндсэн утгаараа тохируулагдах ба хэрэглэгчийн дата бүхэлдээ устана."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"Та Android ТВ төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдсон байна. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаагийн амжилтгүй оролдлогын дараагаас таны Android ТВ төхөөрөмжийг үйлдвэрийн өгөгдмөл төлөвт шинэчлэх бөгөөд хэрэглэгчийн бүх өгөгдөл устах болно."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"Та Android TV төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдсон байна. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаагийн амжилтгүй оролдлогын дараагаас таны Android TV төхөөрөмжийг үйлдвэрийн өгөгдмөл төлөвт шинэчлэх бөгөөд хэрэглэгчийн бүх өгөгдөл устах болно."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"Та утсыг тайлах гэж <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдлоо. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оролдвол утас үйлдвэрийн үндсэн утгаараа тохируулагдах ба хэрэглэгчийн дата бүхэлдээ устана."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"Та таблетыг <xliff:g id="NUMBER">%d</xliff:g> удаа тайлах гэж буруу оролдлоо. Таблет одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
- <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"Та Android ТВ төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдсон байна. Таны Android ТВ төхөөрөмжийг одоо үйлдвэрийн өгөгдмөл төлөвт шинэчилнэ."</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"Та Android TV төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдсон байна. Таны Android TV төхөөрөмжийг одоо үйлдвэрийн өгөгдмөл төлөвт шинэчилнэ."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Та утсыг тайлах гэж <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдлоо. Утас одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Хээг мартсан уу?"</string>
@@ -954,7 +954,7 @@
<string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"Апп нь Хөтчийн зочилж байсан бүх URL-н түүх болон Хөтчийн бүх хавчуургыг унших боломжтой. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадавхтай аппликейшнүүдэд ашиглагдахгүй байх боломжтой."</string>
<string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"вэб хавчуурга болон түүхийг бичих"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"Апп нь таны таблет дээр хадгалагдсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөх боломжтой. Энэ нь апп-д Хөтчийн датаг арилгах эсвэл өөрчлөх боломжийг олгоно. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадвартай аппликейшнд ажиллахгүй байх боломжтой."</string>
- <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Аппад таны Android ТВ төхөөрөмжид хадгалсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөхийг зөвшөөрнө. Энэ нь аппад Хөтчийн өгөгдлийг устгах эсвэл өөрчлөхийг зөвшөөрч болзошгүй. Санамж: энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вэб хөтчийн чадамжтай бусад аппад хэрэгжихгүй байж болзошгүй."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Аппад таны Android TV төхөөрөмжид хадгалсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөхийг зөвшөөрнө. Энэ нь аппад Хөтчийн өгөгдлийг устгах эсвэл өөрчлөхийг зөвшөөрч болзошгүй. Санамж: энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вэб хөтчийн чадамжтай бусад аппад хэрэгжихгүй байж болзошгүй."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"Апп нь таны утсан дээр хадгалагдсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөх боломжтой. Энэ нь апп-д Хөтчийн датаг арилгах эсвэл өөрчлөх боломжийг олгоно. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадвартай аппликейшнд ажиллахгүй байх боломжтой."</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"сэрүүлэг тохируулах"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"Апп нь суулгагдсан сэрүүлэгний апп дээр сэрүүлэг тохируулах боломжтой. Зарим сэрүүлэгний апп нь энэ функцийг дэмжихгүй байж болзошгүй."</string>
@@ -1609,27 +1609,26 @@
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Та PIN кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу бичив. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"Та таблетыг тайлах гэж <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдлоо. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оролдвол таблет үйлдвэрийн үндсэн утгаараа тохируулагдах ба хэрэглэгчийн дата бүхэлдээ устана."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"Та Android ТВ төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдсон байна. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаагийн амжилтгүй оролдлогын дараагаас таны Android ТВ төхөөрөмжийг үйлдвэрийн өгөгдмөл төлөвт шинэчлэх бөгөөд хэрэглэгчийн бүх өгөгдөл устах болно."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"Та Android TV төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдсон байна. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаагийн амжилтгүй оролдлогын дараагаас таны Android TV төхөөрөмжийг үйлдвэрийн өгөгдмөл төлөвт шинэчлэх бөгөөд хэрэглэгчийн бүх өгөгдөл устах болно."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"Та утсыг тайлах гэж <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оролдлоо. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оролдвол утас үйлдвэрийн үндсэн утгаараа тохируулагдах ба хэрэглэгчийн дата бүхэлдээ устана."</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"Та таблетыг тайлах гэж <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдлоо. Таблет одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
- <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"Та Android ТВ төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдсон байна. Таны Android ТВ төхөөрөмжийг одоо үйлдвэрийн өгөгдмөл төлөвт шинэчилнэ."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"Та Android TV төхөөрөмжийнхөө түгжээг тайлахаар <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдсон байна. Таны Android TV төхөөрөмжийг одоо үйлдвэрийн өгөгдмөл төлөвт шинэчилнэ."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"Та утсыг тайлах гэж <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдлоо. Утас одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та таблетаа тайлахын тулд имэйл бүртгэл шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оролдсон тохиолдолд Android ТВ төхөөрөмжийнхөө түгжээг имэйл бүртгэлээрээ тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оролдсон тохиолдолд Android TV төхөөрөмжийнхөө түгжээг имэйл бүртгэлээрээ тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та утсаа тайлахын тулд имэйл бүртгэлээ ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Устгах"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g>-н дэлгэц дээрх үйлчилгээг эхлүүлдэг дэвсгэр нь цаашид R хийцийн ашиглах үеийн зөвшөөрөлгүй болно. go/r-bg-fgs-restriction-г үзэж, алдааны мэдээ илгээнэ үү."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дууг санал болгосноос чанга болгож өсгөх үү?\n\nУрт хугацаанд чанга хөгжим сонсох нь таны сонсголыг муутгаж болно."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Хүртээмжийн товчлолыг ашиглах уу?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Товчлол асаалттай үед дууны түвшний хоёр товчлуурыг хамтад нь 3 секунд дарснаар хандалтын онцлогийг эхлүүлнэ."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Хандалтын онцлогуудыг асаах уу?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дууны түвшний түлхүүрийг хэдэн секундийн турш зэрэг дарах нь хандалтын онцлогуудыг асаадаг. Энэ нь таны төхөөрөмжийн ажиллах зарчмыг өөрчилж болзошгүй.\n\nОдоогийн онцлогууд:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТа сонгосон онцлогуудыг Тохиргоо &gt; Хандалт хэсэгт өөрчлөх боломжтой."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дууны түвшний түлхүүрийг хэдэн секундийн турш зэрэг дарснаар хандалтын онцлогууд асна. Энэ нь таны төхөөрөмжийн ажиллах зарчмыг өөрчилж болзошгүй.\n\nОдоогийн онцлогууд:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТа сонгосон онцлогуудыг Тохиргоо &gt; Хандалт хэсэгт өөрчлөх боломжтой."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g>-г асаах уу?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Дууны түвшний түлхүүрийг хэдэн секундийн турш зэрэг дарах нь хандалтын онцлог болох <xliff:g id="SERVICE">%1$s</xliff:g>-г асаадаг. Энэ нь таны төхөөрөмжийн ажиллах зарчмыг өөрчилж болзошгүй.\n\nТа Тохиргоо &gt; Хандалт хэсэгт энэ товчлолыг өөр онцлогт оноож өөрчлөх боломжтой."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Асаах"</string>
- <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Битгий асаа"</string>
+ <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Бүү асаа"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"ИДЭВХТЭЙ"</string>
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"ИДЭВХГҮЙ"</string>
<string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g>-д таны төхөөрөмжийг бүрэн хянахыг зөвшөөрөх үү?"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index f2bec3160830..e5d19533d27d 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"काढा"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> कडून बॅकग्राउंडने फोरग्राउंडमध्ये सुरू केलेल्या सेवेला भविष्यातील आर बिल्डमध्ये वापर करते वेळची परवानगी नसेल. कृपया go/r-bg-fgs-restriction पहा आणि बगची तक्रार नोंदवा."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"शिफारस केलेल्‍या पातळीच्या वर आवाज वाढवायचा?\n\nउच्च आवाजात दीर्घ काळ ऐकण्‍याने आपल्‍या श्रवणशक्तीची हानी होऊ शकते."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"प्रवेशयोग्यता शॉर्टकट वापरायचा?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट सुरू असताना, दोन्ही व्‍हॉल्‍यूम बटणे तीन सेकंदांसाठी दाबून ठेवल्याने अ‍ॅक्सेसिबिलिटी वैशिष्ट्य सुरू होईल."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index fd6025ec0879..6d2d060d6451 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci telefon anda menggunakan log masuk Google anda.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alih keluar"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Perkhidmatan latar depan dimulakan latar belakang daripada <xliff:g id="PACKAGENAME">%1$s</xliff:g> tidak akan mempunyai kebenaran semasa-dalam-penggunaan dalam binaan R akan datang. Sila lihat go/r-bg-fgs-restriction dan failkan laporan pepijat."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Naikkan kelantangan melebihi paras yang disyokorkan?\n\nMendengar pada kelantangan yang tinggi untuk tempoh yang lama boleh merosakkan pendengaran anda."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Kebolehaksesan?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Apabila pintasan dihidupkan, tindakan menekan kedua-dua butang kelantangan selama 3 saat akan memulakan ciri kebolehaksesan."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index c21a1d78db45..2363860968da 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"သင် ပုံဖော်၍သော့ဖွင့်ခြင်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> အကြိမ် မှန်ကန်စွာ မပြုလုပ်နိုင်ပါ။ နောက်ထပ် <xliff:g id="NUMBER_1">%2$d</xliff:g> အကြိမ် မမှန်ကန်ပါက သင့်ဖုန်းအား အီးမေးလ်အသုံးပြု၍ သော့ဖွင့်ရန် တောင်းဆိုပါလိမ့်မည်။ \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ပြန်လည် ကြိုးစားပါ"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ဖယ်ရှားရန်"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> တွင် မှ စတင်သည့် foreground ဝန်ဆောင်မှုသည် နောက်ထွက်ရှိမည့် R စုပေါင်းစပ်ပေါင်း ပရိုဂရမ်များတွင် အသုံးပြုစဉ်အတွင်း ခွင့်ပြုချက် ရရှိမည်မဟုတ်ပါ။ go/r-bg-fgs-ကန့်သတ်ချက်များကို ကြည့်ပြီး အမှားသတင်းပို့ချက်တစ်ခု တင်သွင်းပါ။"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"အသံကို အကြံပြုထားသည့် ပမာဏထက် မြှင့်ပေးရမလား?\n\nအသံကို မြင့်သည့် အဆင့်မှာ ကြာရှည်စွာ နားထောင်ခြင်းက သင်၏ နားကို ထိခိုက်စေနိုင်သည်။"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ်ကို အသုံးပြုလိုပါသလား။"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ဖြတ်လမ်းလင့်ခ်ကို ဖွင့်ထားစဉ် အသံထိန်းခလုတ် နှစ်ခုစလုံးကို ၃ စက္ကန့်ခန့် ဖိထားခြင်းဖြင့် အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုကို ဖွင့်နိုင်သည်။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 949c7f23e6e7..1d15398f8539 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har tegnet opplåsningsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> gale forsøk, blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Forgrunnstjenesten fra <xliff:g id="PACKAGENAME">%1$s</xliff:g>, som ble startet i bakgrunnen, kommer ikke til å ha tillatelser mens den er i bruk i fremtidige R-delversjoner. Les go/r-bg-fgs-restriction og send inn en feilrapport."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du øke volumet til over anbefalt nivå?\n\nHvis du hører på et høyt volum over lengre perioder, kan det skade hørselen din."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruke tilgjengelighetssnarveien?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når snarveien er på, starter en tilgjengelighetsfunksjon når du trykker inn begge volumknappene i tre sekunder."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index a36035e817a3..a618eb5fb414 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1623,12 +1623,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तपाईँले आफ्नो अनलक ढाँचा गलत रूपमा <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक तान्नु भएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> धेरै असफल प्रयासहरूपछि, तपाईँलाई एउटा इमेल खाताको प्रयोग गरेर तपाईँको फोन अनलक गर्न सोधिने छ।\n\n फेरि <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्।"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"हटाउनुहोस्"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> को पृष्ठभूमिबाट सुरु गरिने अग्रभूमि सेवाका भविष्यमा आउने R बिल्डहरूमा चलाउँदै गर्दा प्रयोग गर्ने अनुमतिको दिइने छैन। कृपया go/r-bg-fgs-restriction हेर्नुहोस् र कुनै बगसम्बन्धी रिपोर्ट फाइल गर्नुहोस्।"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"सिफारिस तहभन्दा आवाज ठुलो गर्नुहुन्छ?\n\nलामो समय सम्म उच्च आवाजमा सुन्दा तपाईँको सुन्ने शक्तिलाई हानी गर्न सक्छ।"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"पहुँच सम्बन्धी सर्टकट प्रयोग गर्ने हो?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"यो सर्टकट सक्रिय हुँदा, ३ सेकेन्डसम्म दुवै भोल्युम बटन थिच्नुले पहुँचसम्बन्धी कुनै सुविधा सुरु गर्ने छ।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"पहुँचसम्बन्धी सुविधाहरू सक्रिय गर्ने हो?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले पहुँचसम्बन्धी सुविधाहरू सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nहालका सुविधाहरू:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतपाईं सेटिङ &gt; पहुँचमा गएर चयन गरिएका सुविधाहरू परिवर्तन गर्न सक्नुहुन्छ।"</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुभयो भने पहुँचसम्बन्धी सुविधाहरू सक्रिय हुन्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nहालका सुविधाहरू:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतपाईं सेटिङ &gt; पहुँचमा गएर चयन गरिएका सुविधाहरू परिवर्तन गर्न सक्नुहुन्छ।"</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गर्ने हो?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले <xliff:g id="SERVICE">%1$s</xliff:g> नामक पहुँचसम्बन्धी सुविधा सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nतपाईं सेटिङ &gt; पहुँचमा गई यो सर्टकटमार्फत अर्को सुविधा खुल्ने बनाउन सक्नुहुन्छ।"</string>
@@ -1655,13 +1654,13 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"रङ्ग उल्टाउने सुविधा"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"रङ्ग सच्याउने सुविधा"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सक्रिय पारियो।"</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> निष्क्रिय पारियो।"</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> प्रयोग गर्न दुवै भोल्युम कुञ्जीहरूलाई तीन सेकेन्डसम्म थिचिराख्नुहोस्"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"तपाईंले पहुँचको बटन ट्याप गर्दा प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस्:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (दुईवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
<string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (तीनवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
- <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"एउटा सुविधाबाट अर्को सुविधामा जान पहुँचको बटनमा छोइराख्नुहोस्।"</string>
+ <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"एउटा सुविधाबाट अर्को सुविधामा जान पहुँच बटन छोइराख्नुहोस्।"</string>
<string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"एउटा सुविधाबाट अर्को सुविधामा जान दुईवटा औँलाले माथितिर स्वाइप गरी स्क्रिनमा छोइराख्नुहोस्।"</string>
<string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"एउटा सुविधाबाट अर्को सुविधामा जान तीनवटा औँलाले माथितिर स्वाइप गरी स्क्रिनमा छोइराख्नुहोस्।"</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"म्याग्निफिकेसन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b1c4fbbf0b09..6feb69f348d3 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -237,7 +237,7 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Telefoonopties"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Schermvergrendeling"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Uitschakelen"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Voeding"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Aan/uit"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Opnieuw opstarten"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Noodgeval"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Bugrapport"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt u gevraagd je telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwijderen"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"De op de achtergrond gestarte voorgrondservice van <xliff:g id="PACKAGENAME">%1$s</xliff:g> heeft geen rechten tijdens gebruik in toekomstige R-builds. Ga naar go/r-bg-fgs-restriction en dien een bugrapport in."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling is ingeschakeld, kun je drie seconden op beide volumeknoppen drukken om een toegankelijkheidsfunctie te starten."</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 5986e7652fa3..6a729dc39870 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -175,7 +175,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"ବହୁତ <xliff:g id="CONTENT_TYPE">%s</xliff:g>କୁ ଡିଲିଟ୍ କରିବା ପାଇଁ ଚେଷ୍ଟା କରାଯାଇଛି"</string>
<string name="low_memory" product="tablet" msgid="5557552311566179924">"ଟାବଲେଟ୍‍ ଷ୍ଟୋରେଜ୍‍ ପୂର୍ଣ୍ଣ ହୋଇଯାଇଛି। ସ୍ଥାନ ଖାଲି କରିବା ପାଇଁ କିଛି ଫାଇଲ୍‍ ଡିଲିଟ୍‍ କରନ୍ତୁ।"</string>
<string name="low_memory" product="watch" msgid="3479447988234030194">"ୱାଚ୍‍ ଷ୍ଟୋରେଜ୍‍ ପୂର୍ଣ୍ଣ ହୋଇଯାଇଛି। ସ୍ଥାନ ଖାଲି କରିବାକୁ କିଛି ଫାଇଲ୍‍ ଡିଲିଟ୍‍ କରନ୍ତୁ।"</string>
- <string name="low_memory" product="tv" msgid="6663680413790323318">"Android ଟିଭି ଡିଭାଇସ୍‌ର ଷ୍ଟୋରେଜ୍ ପୂର୍ଣ୍ଣ ଅଛି। ଜାଗା ଖାଲି କରିବାକୁ କିଛି ଫାଇଲ୍ ଡିଲିଟ୍ କରନ୍ତୁ।"</string>
+ <string name="low_memory" product="tv" msgid="6663680413790323318">"Android TV ଡିଭାଇସ୍‌ର ଷ୍ଟୋରେଜ୍ ପୂର୍ଣ୍ଣ ଅଛି। ଜାଗା ଖାଲି କରିବାକୁ କିଛି ଫାଇଲ୍ ଡିଲିଟ୍ କରନ୍ତୁ।"</string>
<string name="low_memory" product="default" msgid="2539532364144025569">"ଫୋନ୍‍ ଷ୍ଟୋରେଜ୍‍ ପୂର୍ଣ୍ଣ ହୋଇଯାଇଛି। ସ୍ଥାନ ଖାଲି କରିବା ପାଇଁ କିଛି ଫାଇଲ୍‍ ଡିଲିଟ୍‍ କରନ୍ତୁ।"</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
<item quantity="other">ସର୍ଟିଫିକେଟ୍‍ ଅଥରିଟିଗୁଡ଼ିକ ଇନଷ୍ଟଲ୍‍ ହେଲା</item>
@@ -206,7 +206,7 @@
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ଚାଲୁ କରନ୍ତୁ"</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>
+ <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TVର ବିକଳ୍ପଗୁଡ଼ିକ"</string>
<string name="power_dialog" product="default" msgid="1107775420270203046">"ଫୋନ୍‌ ବିକଳ୍ପ"</string>
<string name="silent_mode" msgid="8796112363642579333">"ସାଇଲେଣ୍ଟ ମୋଡ୍"</string>
<string name="turn_on_radio" msgid="2961717788170634233">"ୱେୟାରଲେସ୍‌କୁ ଚାଲୁ କରନ୍ତୁ"</string>
@@ -224,7 +224,7 @@
<string name="reboot_to_reset_message" msgid="3347690497972074356">"ରିଷ୍ଟାର୍ଟ କରାଯାଉଛି…"</string>
<string name="shutdown_progress" msgid="5017145516412657345">"ବନ୍ଦ କରାଯାଉଛି…"</string>
<string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"ଆପଣଙ୍କ ଟାବଲେଟ୍ ବନ୍ଦ ହୋଇଯିବ।"</string>
- <string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍ ବନ୍ଦ ହୋଇଯିବ।"</string>
+ <string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ ବନ୍ଦ ହୋଇଯିବ।"</string>
<string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"ଆପଣଙ୍କ ଘଣ୍ଟା ବନ୍ଦ ହୋଇଯିବ।"</string>
<string name="shutdown_confirm" product="default" msgid="136816458966692315">"ଆପଣଙ୍କ ଫୋନ୍ ବନ୍ଦ ହୋଇଯିବ।"</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"ଆପଣ ବନ୍ଦ କରିବାକୁ ଚାହାନ୍ତି?"</string>
@@ -233,7 +233,7 @@
<string name="recent_tasks_title" msgid="8183172372995396653">"ବର୍ତ୍ତମାନର"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"କୌଣସି ସମ୍ପ୍ରତି ଆପ୍‌ ନାହିଁ।"</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"ଟାବଲେଟ ବିକଳ୍ପ"</string>
- <string name="global_actions" product="tv" msgid="3871763739487450369">"Android ଟିଭିର ବିକଳ୍ପଗୁଡ଼ିକ"</string>
+ <string name="global_actions" product="tv" msgid="3871763739487450369">"Android TVର ବିକଳ୍ପଗୁଡ଼ିକ"</string>
<string name="global_actions" product="default" msgid="6410072189971495460">"ଫୋନ ବିକଳ୍ପ"</string>
<string name="global_action_lock" msgid="6949357274257655383">"ସ୍କ୍ରୀନ୍‌ ଲକ୍‌"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"ପାୱାର୍ ବନ୍ଦ"</string>
@@ -357,7 +357,7 @@
<string name="permdesc_sendSms" msgid="6757089798435130769">"ଆପ୍‌କୁ SMS ମେସେଜ୍ ପଠେଇବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଅପ୍ରତ୍ୟାଶିତ ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ। ହାନୀକାରକ ଆପ୍‌ ଆପଣଙ୍କ ବିନା ସ୍ୱୀକୃତିରେ ମେସେଜ୍‍ ପଠାଇ, ଆପଣଙ୍କ ପଇସା ଖର୍ଚ୍ଚ କରାଇପାରେ।"</string>
<string name="permlab_readSms" msgid="5164176626258800297">"ଆପଣଙ୍କ ଟେକ୍ସଟ୍‍ ମେସେଜ୍‍ (SMS କିମ୍ବା MMS) ପଢ଼ନ୍ତୁ"</string>
<string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"ଆପଣଙ୍କ ଟାବଲେଟ୍‌ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ସମସ୍ତ SMS (ଟେକ୍ସଟ୍‍) ମେସେଜ୍‍ ଏହି ଆପ୍‍ ପଢ଼ିପାରେ।"</string>
- <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ଏହି ଆପ୍ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ SMS (ଟେକ୍ସଟ୍) ପଢ଼ି ପାରିବ।"</string>
+ <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ଏହି ଆପ୍ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ SMS (ଟେକ୍ସଟ୍) ପଢ଼ି ପାରିବ।"</string>
<string name="permdesc_readSms" product="default" msgid="774753371111699782">"ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ସମସ୍ତ SMS (ଟେକ୍ସଟ୍‍) ମେସେଜ୍‍ ଏହି ଆପ୍‍ ପଢ଼ିପାରେ।"</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"ଟେକ୍ସଟ୍‍ ମେସେଜ୍‍ (WAP) ପ୍ରାପ୍ତ କରନ୍ତୁ"</string>
<string name="permdesc_receiveWapPush" msgid="1638677888301778457">"ଆପ୍‌କୁ WAP ମେସେଜିଙ୍ଗକୁ ପ୍ରାପ୍ତ ଓ ବିକାଶ କରିବାକୁ ଦେଇଥାଏ। ଏହି ଅନୁମତିରେ ଆପଣ ସେମାନଙ୍କୁ ଦେଖାଯାଇଥିବା ମେସେଜ୍ ଉପରେ ନଜର ରଖିବା ଏବଂ ଡିଲିଟ୍‍ କରିବାର କ୍ଷମତା ସାମିଲ୍ ଅଛି।"</string>
@@ -379,7 +379,7 @@
<string name="permdesc_useDataInBackground" msgid="1230753883865891987">"ଏହି ଆପ୍‌ ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡରେ ଡାଟା ବ୍ୟବହାର କରିପାରିବ। ଏହା ଦ୍ୱାରା ଅଧିକ ବ୍ୟାଟେରୀ ହୋଇପାରେ।"</string>
<string name="permlab_persistentActivity" msgid="464970041740567970">"ଆପ୍‍କୁ, ସର୍ବଦା ଚାଲୁଥିବା କରନ୍ତୁ"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"ଆପ୍‍ଟି ନିଜକୁ ମେମୋରୀରେ ଭାଗ କରିବାକୁ ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଅନ୍ୟ ଆପ୍‍ଗୁଡ଼ିକ ପାଇଁ ମେମୋରୀ ଉପଲବ୍ଧକୁ କମ୍‌ କରିବା ସହ ଟାବ୍‍ଲେଟ୍‍ଟିକୁ ମନ୍ଥର କରିବ।"</string>
- <string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"ମେମୋରୀରେ ଅବିରତ ଆପ୍ ନିଜକୁ ନିଜେ ଭାଗ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଧୀର କରି ଅନ୍ୟ ଆପ୍ ପାଇଁ ଉପଲବ୍ଧ ମେମୋରୀକୁ ସୀମିତ କରିପାରେ।"</string>
+ <string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"ମେମୋରୀରେ ଅବିରତ ଆପ୍ ନିଜକୁ ନିଜେ ଭାଗ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ଅନ୍ୟ ଆପ୍ସ ପାଇଁ ଉପଲବ୍ଧ ମେମୋରୀକୁ ସୀମିତ କରି ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଧୀର କରିପାରେ।"</string>
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"ଆପ୍‍ଟି ନିଜକୁ ମେମୋରୀରେ ଭାଗ କରିବାକୁ ଦେଇଥାଏ। ଏହାଦ୍ୱାରା ଅନ୍ୟ ଆପ୍‍ଗୁଡ଼ିକ ପାଇଁ ମେମୋରୀ ଉପଲବ୍ଧକୁ କମ୍‌ କରିବା ସହ ଫୋନ୍‍ଟିକୁ ମନ୍ଥର କରିବ।"</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"ଫୋର୍‌ଗ୍ରାଉଣ୍ଡ ସେବାକୁ ଚଲାନ୍ତୁ"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"ଫୋର୍‌ଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
@@ -389,11 +389,11 @@
<string name="permdesc_writeSettings" msgid="8293047411196067188">"ଆପ୍‍କୁ, ସିଷ୍ଟମର ସେଟିଙ୍ଗ ଡାଟା ବଦଳାଇବାକୁ ଦେଇଥାଏ। ହାନୀକାରକ ଆପ୍‍ ଦ୍ୱାରା ଆପଣଙ୍କ ସିଷ୍ଟମର କନଫିଗରେସନ୍‍ ଖରାପ ହୋଇପାରେ।"</string>
<string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"ଆରମ୍ଭ ହେଲେ ଚଲାନ୍ତୁ"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"ସିଷ୍ଟମ୍‍ ବୁଟ୍ ଶେଷ ହେବା କ୍ଷଣି ଆପ୍‍ଟିକୁ ସ୍ୱତଃ ଆରମ୍ଭ ହେବାକୁ ଦେଇଥାଏ। ଏହା କାରଣରୁ ଟାବଲେଟଟ୍‌ଟି ଚାଲୁ ହେବାରେ ଅଧିକ ସମୟ ଲାଗିପାରେ ଏବଂ ଆପ୍‌ଟି ଲଗାତାର ଚାଲିବା ଦ୍ୱାରା ସମଗ୍ର ଟାବଲେଟଟ୍‌ ମନ୍ଥର ହୋଇଯାଇପାରେ।"</string>
- <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"ଯେତେ ଶୀଘ୍ର ସମ୍ଭବ ସିଷ୍ଟମ୍ ବୁଟିଂ ସମାପ୍ତ ହେବା ପରେ ଆପ୍ ନିଜକୁ ନିଜେ ଆରମ୍ଭ ହେବାକୁ ଅନୁମତି ଦିଏ। ଏହା Android ଟିଭି ଡିଭାଇସ୍ ଆରମ୍ଭ କରିବାକୁ ଅଧିକ ସମୟ ନେଇଥାଏ ଏବଂ ସର୍ବଦା ଚାଲି ସମଗ୍ର ଡିଭାଇସ୍‌କୁ ଧୀର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"ଯେତେ ଶୀଘ୍ର ସମ୍ଭବ ସିଷ୍ଟମ୍ ବୁଟିଂ ସମାପ୍ତ ହେବା ପରେ ଆପ୍ ନିଜକୁ ନିଜେ ଆରମ୍ଭ ହେବାକୁ ଅନୁମତି ଦିଏ। ଏହା Android TV ଡିଭାଇସ୍ ଆରମ୍ଭ କରିବାକୁ ଅଧିକ ସମୟ ନେବାକୁ ଦେଇଥାଏ ଏବଂ ସର୍ବଦା ଚାଲି ସମଗ୍ର ଡିଭାଇସ୍‌କୁ ଧୀର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"ସିଷ୍ଟମ୍‍ ବୁଟ୍ ଶେଷ ହେବା କ୍ଷଣି ଆପ୍‍ଟିକୁ ସ୍ୱତଃ ଆରମ୍ଭ ହେବାକୁ ଦେଇଥାଏ। ଏହା କାରଣରୁ ଫୋନ୍‍ଟି ଚାଲୁ ହେବାରେ ଅଧିକ ସମୟ ଲାଗିପାରେ ଏବଂ ଆପ୍‌ଟି ଲଗାତାର ଚାଲିବା ଦ୍ୱାରା ସମଗ୍ର ଫୋନ୍‌ ମନ୍ଥର ହୋଇଯାଇପାରେ।"</string>
<string name="permlab_broadcastSticky" msgid="4552241916400572230">"ଷ୍ଟିକୀ ବ୍ରୋଡକାଷ୍ଟ ପଠାନ୍ତୁ"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"ଆପ୍‌କୁ ଷ୍ଟିକୀ ବ୍ରଡ୍‍କାଷ୍ଟ ପଠାଇବାକୁ ଅନୁମତି ଦେଇଥାଏ, ଯାହା ବ୍ରଡ୍‍କାଷ୍ଟ ସମାପ୍ତ ହେବାପରେ ବି ରହିଥାଏ। ଅତ୍ୟଧିକ ଉପଯୋଗ ଦ୍ୱାରା ଟାବଲେଟ୍‍ ମନ୍ଥର ହୋଇପାରେ କିମ୍ବା ଅଧିକ ମେମୋରୀର ବ୍ୟବହାର କରିବା କାରଣରୁ ଏହା ଅସ୍ଥିର ହୋଇପାରେ।"</string>
- <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ଷ୍ଟିକି ବ୍ରଡକାଷ୍ଟ୍ ପଠାଇବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ, ଯାହା ବ୍ରଡକାଷ୍ଟ୍ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତ୍ୟଧିକ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଧୀର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
+ <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ଷ୍ଟିକି ବ୍ରଡକାଷ୍ଟ୍ ପଠାଇବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ, ଯାହା ବ୍ରଡକାଷ୍ଟ୍ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତ୍ୟଧିକ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଧୀର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ଷ୍ଟିକୀ ବ୍ରଡ୍‌କାଷ୍ଟ ପଠାଇବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ, ଯାହା ବ୍ରଡ୍‌କାଷ୍ଟ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତିରିକ୍ତ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଫୋନ୍‌କୁ ମନ୍ଥର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ଆପଣଙ୍କ ଯୋଗାଯୋଗ ପଢ଼ନ୍ତୁ"</string>
<string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ଏହା ଆପଣଙ୍କ ଟାବ୍‌ଲେଟ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗଗୁଡ଼ିକ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର ଟାବ୍‌ଲେଟ୍‌ରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ ଯୋଗାଯୋଗଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ଆପ୍ସର ଆକ୍ସେସ୍ ରହିବ। ଆପଣ ଇନ୍‌ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜାଣତରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍ କରିପାରେ।"</string>
@@ -407,17 +407,17 @@
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ଏହି ଆପ୍‍ ଆପଣଙ୍କ କଲ୍‍ ହିଷ୍ଟୋରୀ ପଢ଼ିପାରେ।"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"କଲ୍‍ ଲଗ୍‍ ଲେଖନ୍ତୁ"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"ଇନ୍‍କମିଙ୍ଗ ତଥା ଆଉଟ୍‍ଗୋଇଙ୍ଗ କଲ୍‌ ଡାଟା ସହ ଆପଣଙ୍କ ଟାବ୍‍ଲେଟ୍‍ର କଲ୍‍ ଲଗ୍‍ ବଦଳାଇବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ କଲ୍‍ ଲଗ୍‍ ଲିଭାଇବାକୁ କିମ୍ବା ବଦଳାଇବାକୁ ଏହା ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
- <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"ଇନ୍‍କମିଂ ତଥା ଆଉଟ୍‌ଗୋଇଂ କଲ୍ ଡାଟା ସହ ଆପଣଙ୍କ Android ଟିଭି ଡିଭାଇସ୍‌ର କଲ୍ ଲଗ୍ ସଂଶୋଧନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। କ୍ଷତିକାରକ ଆପ୍‌ଗୁଡ଼ିକ ଆପଣଙ୍କ କଲ୍ ଲଗ୍ ଲିଭାଇବାକୁ କିମ୍ବା ସଂଶୋଧନ କରିବା ପାଇଁ ଏହାକୁ ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"ଇନ୍‍କମିଂ ତଥା ଆଉଟ୍‌ଗୋଇଂ କଲ୍ ଡାଟା ସହ ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ର କଲ୍ ଲଗ୍ ସଂଶୋଧନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। କ୍ଷତିକାରକ ଆପ୍‌ଗୁଡ଼ିକ ଆପଣଙ୍କ କଲ୍ ଲଗ୍ ଲିଭାଇବାକୁ କିମ୍ବା ସଂଶୋଧନ କରିବା ପାଇଁ ଏହାକୁ ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
<string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"ଇନ୍‍କମିଙ୍ଗ ତଥା ଆଉଟ୍‍ଗୋଇଙ୍ଗ କଲ୍‌ ଡାଟା ସହ ଆପଣଙ୍କ ଫୋନ୍‍ର କଲ୍‍ ଲଗ୍‍ ବଦଳାଇବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ କଲ୍‍ ଲଗ୍‍ ଲିଭାଇବାକୁ କିମ୍ବା ବଦଳାଇବାକୁ ଏହା ବ୍ୟବହାର କରିପାରନ୍ତି।"</string>
<string name="permlab_bodySensors" msgid="3411035315357380862">"ବଡୀ ସେନ୍ସର୍‍ ଆକ୍ସେସ୍‍ କରେ (ଯେପରିକି ହୃଦ୍‍ ହାର ମନିଟର୍‍)"</string>
<string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"ଆପ୍‌କୁ ସେନ୍ସର୍ ଡେଟା ପର୍ଯ୍ୟନ୍ତ ପହଞ୍ଚିବାକୁ ଦେଇଥାଏ, ଯାହା ଆପଣଙ୍କ ଶାରୀରିକ ସ୍ଥିତିର ନିରୀକ୍ଷଣ କରିଥାଏ, ଯେପରିକି ଆପଣଙ୍କ ହୃଦୟ ସ୍ତର।"</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"କ୍ୟାଲେଣ୍ଡର୍‍ ଇଭେଣ୍ଟ ଏବଂ ବିବରଣୀ ପଢ଼େ"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"ଆପଣଙ୍କ ଟାବଲେଟ୍‌ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ସମସ୍ତ କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟ ଏହି ଆପ୍‍ ପଢ଼ିପାରେ ଏବଂ ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର ଡାଟା ସେୟାର୍‍ କରିପାରେ କିମ୍ବା ସେଭ୍‍ କରିପାରେ।"</string>
- <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ଏହି ଆପ୍ ଆପଣଙ୍କ Android ଟିଭି ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟ ପଢ଼ିପାରେ ଏବଂ ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର ଡାଟା ସେୟାର୍ କରିପାରେ କିମ୍ବା ସେଭ୍ କରିପାରେ।"</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ଏହି ଆପ୍ ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟ ପଢ଼ିପାରେ ଏବଂ ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର ଡାଟା ସେୟାର୍ କରିପାରେ କିମ୍ବା ସେଭ୍ କରିପାରେ।"</string>
<string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ସମସ୍ତ କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟ ଏହି ଆପ୍‍ ପଢ଼ିପାରେ ଏବଂ ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର ଡାଟା ସେୟାର୍‍ କରିପାରେ କିମ୍ବା ସେଭ୍‍ କରିପାରେ।"</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟରେ ଯୋଡ଼ନ୍ତୁ କିମ୍ବା ସଂଶୋଧନ କରନ୍ତୁ ଏବଂ ମାଲିକଙ୍କ ଅଜାଣତରେ ଅତିଥିମାନଙ୍କୁ ଇମେଲ୍ ପଠାନ୍ତୁ।"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଟାବଲେଟ୍‌ରେ କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟ ଯୋଡ଼ିପାରେ, ବାହାର କରିପାରେ କିମ୍ବା ବଦଳାଇପାରେ। ଏହି ଆପ୍‍ ଏପରି ମେସେଜ୍‍ ପଠାଇପାରେ, ଯାହା କ୍ୟାଲେଣ୍ଡର ମାଲିକଙ୍କଠାରୁ ଆସିଥିବା ପରି ଜଣାପଡ଼େ କିମ୍ବା ମାଲିକଙ୍କୁ ନଜଣାଇ ଇଭେଣ୍ଟରେ ପରିବର୍ତ୍ତନ କରିପାରେ।"</string>
- <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ଏହି ଆପ୍, ଆପଣଙ୍କ Android ଟିଭି ଡିଭାଇସ୍‌ରେ କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟଗୁଡ଼ିକୁ ଯୋଗ କରିପାରେ, କାଢ଼ି ପାରେ କିମ୍ବା ପରିବର୍ତ୍ତନ କରିପାରେ। ଏହି ଆପ୍ ଏପରି ମେସେଜ୍ ପଠାଇ ପାରେ, ଯାହା କ୍ୟାଲେଣ୍ଡର ମାଲିକଙ୍କଠାରୁ ଆସିଥିବା ପରି ଜଣାପଡ଼େ କିମ୍ବା ମାଲିକଙ୍କୁ ନଜଣାଇ ଇଭେଣ୍ଟରେ ପରିବର୍ତ୍ତନ କରିପାରେ।"</string>
+ <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ଏହି ଆପ୍, ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ରେ କ୍ୟାଲେଣ୍ଡର ଇଭେଣ୍ଟଗୁଡ଼ିକୁ ଯୋଗ କରିପାରେ, କାଢ଼ି ପାରେ କିମ୍ବା ପରିବର୍ତ୍ତନ କରିପାରେ। ଏହି ଆପ୍ ଏପରି ମେସେଜ୍ ପଠାଇ ପାରେ, ଯାହା କ୍ୟାଲେଣ୍ଡର ମାଲିକଙ୍କଠାରୁ ଆସିଥିବା ପରି ଜଣାପଡ଼େ କିମ୍ବା ମାଲିକଙ୍କୁ ନଜଣାଇ ଇଭେଣ୍ଟରେ ପରିବର୍ତ୍ତନ କରିପାରେ।"</string>
<string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ଏହି ଆପ୍‍, ଆପଣଙ୍କ ଫୋନ୍‌ରେ କ୍ୟାଲେଣ୍ଡର୍‌ ଇଭେଣ୍ଟଗୁଡ଼ିକୁ ଯୋଡ଼ିପାରେ, ବାହାର କରିପାରେ କିମ୍ବା ବଦଳାଇପାରେ। କ୍ୟାଲେଣ୍ଡର୍‌ ମାଲିକଙ୍କ ପାଖରୁ ଆସିଥିବା ପରି ଜଣା‍ପଡ଼ିବା ମେସେଜ୍‍କୁ ଏହି ଆପ୍‍ ପଠାଇପାରେ କିମ୍ବା ମାଲିକଙ୍କୁ ନଜଣାଇ ଇଭେଣ୍ଟ ବଦଳାଇପାରେ।"</string>
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ଅତିରିକ୍ତ ଲୋକେସନ୍ ପ୍ରଦାନକାରୀ କମାଣ୍ଡକୁ ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ଅତିରିକ୍ତ ଲୋକେସନ୍‍ ପ୍ରଦାନକାରୀ କମାଣ୍ଡ ଆକ୍ସେସ୍‌ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। GPS କିମ୍ବା ଅନ୍ୟ ଲୋକେସନ୍‍ ସୋର୍ସଗୁଡିକରେ ଆପ୍‍ଟି ପ୍ରଭାବ ପକାଇପାରେ।"</string>
@@ -462,7 +462,7 @@
<string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"ଏହି ଡିଭାଇସର ଫୋନ୍‍ ନମ୍ବର ଆକ୍ସେସ୍‍ କରିବାକୁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
<string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"କାର ସ୍କ୍ରିନକୁ ଚାଲୁ ରଖନ୍ତୁ"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1527660973931694000">"ଟାବଲେଟ୍‌କୁ ସ୍ଲୀପିଙ୍ଗ ମୋଡ୍‌କୁ ଯିବାକୁ ରୋକନ୍ତୁ"</string>
- <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"ସ୍ଲିପିଂରୁ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ପ୍ରତିରୋଧ କରନ୍ତୁ"</string>
+ <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"ସ୍ଲିପିଂରୁ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ପ୍ରତିରୋଧ କରନ୍ତୁ"</string>
<string name="permlab_wakeLock" product="default" msgid="569409726861695115">"ଫୋନକୁ ସ୍ଲୀପିଙ୍ଗ ମୋଡ୍‌କୁ ଯିବାକୁ ରୋକନ୍ତୁ"</string>
<string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"କାର ସ୍କ୍ରିନକୁ ଚାଲୁ ରଖିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"ଆପ୍‍କୁ, ଟାବଲେଟ୍‍ଟିକୁ ସ୍ଲୀପ୍‍ ମୋଡ୍‍କୁ ଯିବାରେ ପ୍ରତିରୋଧ କରିବାକୁ ଦେଇଥାଏ।"</string>
@@ -470,7 +470,7 @@
<string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"ଆପ୍‍କୁ, ଫୋନ୍‌ଟିକୁ ସ୍ଲୀପ୍‍ ମୋଡ୍‍କୁ ଯିବାରେ ପ୍ରତିରୋଧ କରିବାକୁ ଦେଇଥାଏ।"</string>
<string name="permlab_transmitIr" msgid="8077196086358004010">"ଇନଫ୍ରାରେଡ୍‍ ସଂଚାରିତ କରନ୍ତୁ"</string>
<string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"ଟାବଲେଟ୍‍ର ଇନଫ୍ରାରେଡ୍‍ ଟ୍ରାନ୍ସମିଟର୍‍ ବ୍ୟବହାର କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
- <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ର ଇନ୍‍ଫ୍ରାରେଡ୍ ଟ୍ରାନ୍ସମିଟର୍ ବ୍ୟବହାର କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ର ଇନ୍‍ଫ୍ରାରେଡ୍ ଟ୍ରାନ୍ସମିଟର୍ ବ୍ୟବହାର କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"ଫୋନ୍‍ର ଇନଫ୍ରାରେଡ୍‍ ଟ୍ରାନ୍ସମିଟର୍‍ ବ୍ୟବହାର କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_setWallpaper" msgid="6959514622698794511">"ୱାଲପେପର୍‍ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="permdesc_setWallpaper" msgid="2973996714129021397">"ଆପ୍‍କୁ, ସିଷ୍ଟମ୍‍ ୱାଲପେପର୍‍ ସେଟ୍‍ କରିବାକୁ ଦେଇଥାଏ।"</string>
@@ -478,11 +478,11 @@
<string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"ଆପ୍‍କୁ, ସିଷ୍ଟମ୍‍ ୱାଲପେପର୍‍ ଆକାରର ସୂଚନା ସେଟ୍‍ କରିବାକୁ ଦେଇଥାଏ।"</string>
<string name="permlab_setTimeZone" msgid="7922618798611542432">"ଟାଇମ୍ ଜୋନ୍‍ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"ଆପ୍‍କୁ, ଟାବଲେଟ୍‌ର ଟାଇମ୍‍ ଜୋନ୍‍ ବଦଳାଇବାକୁ ଦେଇଥାଏ।"</string>
- <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ର ଟାଇମ୍ ଜୋନ୍ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ର ଟାଇମ୍ ଜୋନ୍ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"ଆପ୍‍କୁ, ଫୋନ୍‍ର ଟାଇମ୍‍ ଜୋନ୍‍ ବଦଳାଇବାକୁ ଦେଇଥାଏ।"</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"ଡିଭାଇସ୍‍ରେ ଆକାଉଣ୍ଟ ଖୋଜନ୍ତୁ"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"ଟାବଲେଟ୍‌ ଦ୍ୱାରା ପରିଚିତ ଆକାଉଣ୍ଟର ତାଲିକା ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣ ଇନଷ୍ଟଲ୍‍ କରିଥିବା ଆପ୍ଲିକେଶନ୍‍ ଦ୍ୱାରା ତିଆରି କରାଯାଇଥିବା କୌଣସି ଆକାଉଣ୍ଟ ବି ଏଥିରେ ସାମିଲ୍ ହୋଇପାରେ।"</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଜଣାଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକର ତାଲିକା ପାଇବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣ ଇନ୍‌ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ଲିକେସନ୍ ମାଧ୍ୟମରେ ଏହା ଯେ କୌଣସି ଆକାଉଣ୍ଟକୁ ହୁଏତ ଅନ୍ତର୍ଭୁକ୍ତ କରିପାରେ।"</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଜଣାଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକର ତାଲିକା ପାଇବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣ ଇନ୍‌ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ଲିକେସନ୍ ମାଧ୍ୟମରେ ଏହା ଯେ କୌଣସି ଆକାଉଣ୍ଟକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରିପାରେ।"</string>
<string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"ଫୋନ୍‌ ଦ୍ୱାରା ପରିଚିତ ଆକାଉଣ୍ଟର ତାଲିକା ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣ ଇନଷ୍ଟଲ୍‍ କରିଥିବା ଆପ୍ଲିକେଶନ୍‍ ଦ୍ୱାରା ତିଆରି କରାଯାଇଥିବା କୌଣସି ଆକାଉଣ୍ଟ ବି ଏଥିରେ ସାମିଲ୍ ହୋଇପାରେ।"</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"ନେଟ୍‍ୱର୍କ ସଂଯୋଗ ଦେଖନ୍ତୁ"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"କେଉଁ ନେଟ୍‌ୱର୍କ ଉପସ୍ଥିତ ତଥା ସଂଯୁକ୍ତ ଅଛି, ତାହା ବିଷୟରେ ସୂଚନା ଦେଖିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
@@ -498,21 +498,21 @@
<string name="permdesc_changeWifiState" msgid="7170350070554505384">"ଆପ୍‌କୁ ୱାଇ-ଫାଇ ଆକ୍ସେସ୍‍ ପଏଣ୍ଟ ସହିତ ସଂଯୋଗ ଓ ବିଚ୍ଛିନ୍ନ କରିବାକୁ ତଥା ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପାଇଁ ଡିଭାଇସ୍‌ କନଫିଗରେଶନ୍‍ରେ ପରିବର୍ତ୍ତନ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"ୱାଇ-ଫାଇ ମଲ୍ଟିକାଷ୍ଟ ରିସେପଶନ ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"କେବଳ ଆପଣଙ୍କ ଟାବ୍‍ଲେଟ୍‍ ନୁହେଁ, ବରଂ ମଲ୍ଟିକାଷ୍ଟ ଠିକଣାଗୁଡ଼ିକ ବ୍ୟବହାର କରି ଏକ ୱାଇ-ଫାଇ ନେଟ୍‍ୱର୍କରେ ଥିବା ସମସ୍ତ ଡିଭାଇସ୍‌‍କୁ ପଠାଯିବା ପ୍ୟାକେଟ୍‍ଗୁଡ଼ିକ ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍‍ଟି ଅନୁମତି ଦେଇଥାଏ। ଅଣ-ମଲ୍ଟିକାଷ୍ଟ ମୋଡ୍‍ ତୁଳନାରେ ଏହା ଅଧିକ ପାୱାର୍‍ ବ୍ୟବହାର କରେ।"</string>
- <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"କେବଳ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍ ନୁହେଁ, ମଲ୍ଟିକାଷ୍ଟ ଠିକଣାଗୁଡ଼ିକୁ ବ୍ୟବହାର କରି ଏକ ୱାଇ-ଫାଇ ନେଟ୍‌ୱାର୍କରେ ସମସ୍ତ ଡିଭାଇସ୍‍କୁ ପଠାଯାଇଥିବା ପ୍ୟାକେଟ୍ ପ୍ରାପ୍ତ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ମଲ୍ଟିକାଷ୍ଟ ମୋଡ୍ ନଥିବା ତୁଳନାରେ ଅଧିକ ପାୱାର୍ ବ୍ୟବହାର କରିଥାଏ।"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"କେବଳ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ ନୁହେଁ, ମଲ୍ଟିକାଷ୍ଟ ଠିକଣାଗୁଡ଼ିକୁ ବ୍ୟବହାର କରି ଏକ ୱାଇ-ଫାଇ ନେଟ୍‌ୱାର୍କରେ ସମସ୍ତ ଡିଭାଇସ୍‍କୁ ପଠାଯାଇଥିବା ପ୍ୟାକେଟ୍ ପ୍ରାପ୍ତ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ମଲ୍ଟିକାଷ୍ଟ ମୋଡ୍ ନଥିବା ତୁଳନାରେ ଅଧିକ ପାୱାର୍ ବ୍ୟବହାର କରିଥାଏ।"</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"କେବଳ ଆପଣଙ୍କ ଫୋନ୍‍ ନୁହେଁ, ବରଂ ମଲ୍ଟିକାଷ୍ଟ ଠିକଣାଗୁଡ଼ିକ ବ୍ୟବହାର କରି ଏକ ୱାଇ-ଫାଇ ନେଟ୍‍ୱର୍କରେ ଥିବା ସମସ୍ତ ଡିଭାଇସ୍‌‍କୁ ପଠାଯିବା ପ୍ୟାକେଟ୍‍ଗୁଡ଼ିକ ପ୍ରାପ୍ତ କରିବାକୁ ଆପ୍‍ଟି ଅନୁମତି ଦେଇଥାଏ। ଅଣ-ମଲ୍ଟିକାଷ୍ଟ ମୋଡ୍‍ ତୁଳନାରେ ଏହା ଅଧିକ ପାୱାର୍‍ ବ୍ୟବହାର କରେ।"</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"ବ୍ଲୁଟୂଥ୍‍‍ ସେଟିଙ୍ଗ ଆକ୍ସେସ୍‌ କରନ୍ତୁ"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"ସ୍ଥାନୀୟ ବ୍ଲୁ-ଟୁଥ, ଟାବଲେଟ୍‍କୁ କନଫିଗର୍ କରିବାକୁ ଏବଂ ରିମୋର୍ଟ ଡିଭାଇସ୍‌କୁ ଚିହ୍ନାଇବା ତଥା ସେଗୁଡ଼ିକୁ ପେୟାର୍‍ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
- <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ରେ ବ୍ଲୁଟୁଥ୍‍ର କନଫିଗର୍ କରିବା ପାଇଁ ଏବଂ ରିମୋଟ୍ ଡିଭାଇସ୍‌ଗୁଡ଼ିକୁ ଖୋଜିବା ସହ ପେୟାର୍ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ରେ ବ୍ଲୁଟୁଥ୍‍ର କନଫିଗର୍ କରିବା ପାଇଁ ଏବଂ ରିମୋଟ୍ ଡିଭାଇସ୍‌ଗୁଡ଼ିକୁ ଖୋଜିବା ସହ ପେୟାର୍ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"ସ୍ଥାନୀୟ ବ୍ଲୁ-ଟୁଥ, ଫୋନ୍‍କୁ କନଫିଗର୍ କରିବାକୁ ଏବଂ ରିମୋର୍ଟ ଡିଭାଇସ୍‌କୁ ଚିହ୍ନାଇବା ତଥା ସେଗୁଡ଼ିକୁ ପେୟାର୍‍ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_accessWimaxState" msgid="7029563339012437434">"WiMAX ସହିତ ସଂଯୋଗ ଏବଂ ଏଥିରୁ ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string>
<string name="permdesc_accessWimaxState" msgid="5372734776802067708">"WiMAX ସକ୍ଷମ କି ନାହିଁ ସ୍ଥିର କରିବାକୁ ଏବଂ ସଂଯୁକ୍ତ ଥିବା କୌଣସି WiMAX ନେଟ୍‌ୱର୍କ ବିଷୟରେ ସୂଚନା ପାଇଁ ଆପ୍‌‍କୁ ଅନୁମତି ଦେଇଥାଏ ।"</string>
<string name="permlab_changeWimaxState" msgid="6223305780806267462">"WiMAX ସ୍ଥିତିକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"WiMAX ନେଟ୍‌ୱର୍କରୁ ଟାବଲେଟ୍‌ ସଂଯୋଗ କରିବାକୁ ଏବଂ ବିଚ୍ଛିନ୍ନ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
- <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"WiMAX ନେଟ୍‌ୱାର୍କରୁ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍ ସଂଯୋଗ କରିବାକୁ ଏବଂ ବିଚ୍ଛିନ୍ନ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"WiMAX ନେଟ୍‌ୱାର୍କରୁ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ ସଂଯୋଗ କରିବାକୁ ଏବଂ ବିଚ୍ଛିନ୍ନ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"WiMAX ନେଟ୍‌ୱର୍କରୁ ଫୋନ୍ ସଂଯୋଗ କରିବାକୁ ଏବଂ ବିଚ୍ଛିନ୍ନ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_bluetooth" msgid="586333280736937209">"ବ୍ଲୁଟୂଥ୍‍‍ ଡିଭାଇସ୍‍ ଦେଖନ୍ତୁ"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ଟାବଲେଟ୍‌ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍‌ର କନଫିଗରେଶନ୍‍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍‍ କରାଯାଇଥିବା ଡିଭାଇସ୍‌ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
- <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ରେ ବ୍ଲୁଟୁଥ୍‍ର କନଫିଗ୍‌ରେସନ୍ ଦେଖିବା ପାଇଁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍‌ଗୁଡ଼ିକ ସହ ସଂଯୋଗଗୁଡ଼ିକୁ ତିଆରି ଏବଂ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ରେ ବ୍ଲୁଟୁଥ୍‍ର କନଫିଗ୍‌ରେସନ୍ ଦେଖିବା ପାଇଁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍‌ଗୁଡ଼ିକ ସହ ସଂଯୋଗଗୁଡ଼ିକୁ ତିଆରି ଏବଂ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ଫୋନ୍‌ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍‌ର କନଫିଗରେଶନ୍‍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍‍ କରାଯାଇଥିବା ଡିଭାଇସ୍‌ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ପସନ୍ଦର NFC ପେମେଣ୍ଟ ସେବା ସୂଚନା"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ପଞ୍ଜିକୃତ ଯନ୍ତ୍ର ଏବଂ ମାର୍ଗ ଲକ୍ଷସ୍ଥଳ ପରି ପସନ୍ଦର nfc ପେମେଣ୍ଟ ସେବା ସୂଚନା ପାଇବାକୁ ଆପ୍ ଅନୁମତି କରିଥାଏ।"</string>
@@ -673,10 +673,10 @@
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ଲକ୍‍ ସ୍କ୍ରୀନ୍‍ ପାସ୍‌ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"ସ୍କ୍ରୀନ୍-ଅନଲକ୍ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରନ୍ତୁ"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ସ୍କ୍ରୀନ୍‍ ଅନଲକ୍‍ କରିବାବେଳେ ଟାଇପ୍‍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍‍କୁ ଲକ୍‍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍‍ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟ୍‍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
- <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ସ୍କ୍ରିନ୍ ଅନ୍‌ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରେ ଏବଂ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଆପଣଙ୍କ Android ଟିଭି ଡିଭାଇସ୍‌ର ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦେଇଥାଏ।"</string>
+ <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ସ୍କ୍ରିନ୍ ଅନ୍‌ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ର ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ସ୍କ୍ରୀନ୍‍ ଅନଲକ୍‍ କରିବାବେଳେ ଟାଇପ୍‍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଫୋନ୍‍କୁ ଲକ୍‍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍‍ କରାଯାଇଥାଏ, ତେବେ ଫୋନ୍‍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ସ୍କ୍ରୀନ୍‍ ଅନଲକ୍‍ କରିବାବେଳେ ଟାଇପ୍‍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍‍କୁ ଲକ୍‍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱର୍ଡ ଟାଇପ୍‍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ସ୍କ୍ରିନ୍ ଅନ୍‌ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରେ ଏବଂ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଏ।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ସ୍କ୍ରିନ୍ ଅନ୍‌ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ସ୍କ୍ରୀନ୍‍ ଅନଲକ୍‍ କରିବାବେଳେ ଟାଇପ୍‍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଫୋନ୍‍କୁ ଲକ୍‍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱର୍ଡ ଟାଇପ୍‍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
<string name="policylab_resetPassword" msgid="214556238645096520">"ସ୍କ୍ରିନ୍ ଲକ୍ ବଦଳାଏ"</string>
<string name="policydesc_resetPassword" msgid="4626419138439341851">"ସ୍କ୍ରିନ୍ ଲକ୍‍ ବଦଳାଏ।"</string>
@@ -684,11 +684,11 @@
<string name="policydesc_forceLock" msgid="1008844760853899693">"ସ୍କ୍ରିନ୍ କିପରି ଓ କେତେବେଳେ ଲକ୍‍ କରାଯିବ, ତାହା ନିୟନ୍ତ୍ରଣ କରେ।"</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"ସମସ୍ତ ଡାଟା ଖାଲି କରିବା"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଟାବ୍‍ଲେଟ୍‍ର ଡାଟା ଲିଭାଇଥାଏ।"</string>
- <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ବିନା ଆଲର୍ଟରେ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ର ଡାଟା ଲିଭାନ୍ତୁ।"</string>
+ <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ବିନା ଚେତାବନୀରେ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ର ଡାଟା ଲିଭାନ୍ତୁ।"</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ଫୋନ୍‍ର ଡାଟା ଲିଭାଇଥାଏ।"</string>
<string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ୟୁଜର୍‍ ଡାଟା ଲିଭାନ୍ତୁ"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ବିନା ଚେତାବନୀରେ ଏହି ଟାବଲେଟରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
- <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ବିନା ଚେତାବନୀରେ ଏହି Android ଟିଭି ଡିଭାଇସ୍‌ରେ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ବିନା ଚେତାବନୀରେ ଏହି Android TV ଡିଭାଇସ୍‌ରେ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ବିନା ଚେତାବନୀରେ ଏହି ଫୋନରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
<string name="policylab_setGlobalProxy" msgid="215332221188670221">"ଗ୍ଲୋବଲ୍ ପ୍ରକ୍ସୀ ଡିଭାଇସ୍‌କୁ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ପଲିସୀ ସକ୍ଷମ କରାଯାଇଥିବାବେଳେ ବ୍ୟବହାର କରିବା ପାଇଁ ଗ୍ଲୋବାଲ୍‍ ପ୍ରକ୍ସୀ ସେଟ୍‍ କରନ୍ତୁ। କେବଳ ଡିଭାଇସ୍‍ ମାଲିକ ଗ୍ଲୋବାଲ୍‍ ପ୍ରକ୍ସୀ ସେଟ୍‍ କରିପାରିବେ।"</string>
@@ -838,7 +838,7 @@
<string name="faceunlock_multiple_failures" msgid="681991538434031708">"ମାଲିକର ମୁହଁ ଚିହ୍ନି ଅନଲକ୍‍ କରିବାର ସର୍ବାଧିକ ଧାର୍ଯ୍ୟ ସୀମା ଅତିକ୍ରମ କଲା"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"କୌଣସି SIM କାର୍ଡ ନାହିଁ"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ଟାବଲେଟ୍‌ରେ କୌଣସି SIM‍ କାର୍ଡ ନାହିଁ।"</string>
- <string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="1408695081255172556">"ଫୋନ୍‌ରେ କୌଣସି SIM‍ କାର୍ଡ ନାହିଁ।"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8473601862688263903">"ଏକ SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="3664999892038416334">"SIM କାର୍ଡ ନାହିଁ କିମ୍ବା ଖରାପ ଅଛି। SIM କାର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
@@ -861,13 +861,13 @@
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"ଆପଣଙ୍କ ପାସୱର୍ଡକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଟାଇପ୍‍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"ଆପଣଙ୍କ PINକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଟାଇପ୍‍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ, Google ସାଇନ୍‌-ଇନ୍‍ ବ୍ୟବହାର କରି ଆପଣଙ୍କୁ ନିଜ ଟାବଲେଟ୍‍କୁ ଅନଲକ୍‍ କରିବାକୁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"ଆପଣ ଆପଣଙ୍କର ଲକ୍ ଖୋଲିବା ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଆଙ୍କିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଆପଣଙ୍କୁ Google ସାଇନ୍ଇନ୍ ବ୍ୟବହାର କରି ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ। \n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ମଧ୍ୟରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"ଆପଣ ଆପଣଙ୍କର ଅନଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଆଙ୍କିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଆପଣଙ୍କୁ Google ସାଇନ୍ଇନ୍ ବ୍ୟବହାର କରି ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ। \n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ମଧ୍ୟରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ, Google ସାଇନ୍‌-ଇନ୍‍ ବ୍ୟବହାର କରି ଆପଣଙ୍କୁ ନିଜ ଫୋନ୍‍କୁ ଅନଲକ୍‍ କରିବାକୁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"ଟାବଲେଟ୍‍କୁ ଅନ୍‌ଲକ୍‌ କରିବା ପାଇଁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ, ଟାବଲେଟ୍‍ଟି ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ ଏବଂ ଆପଣ ସମସ୍ତ ୟୁଜର୍‍ ଡାଟା ହରାଇବେ।"</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍ ଡିଫଲ୍ଟକୁ ଫ୍ୟାକ୍ଟୋରୀ ରିସେଟ୍ କରାଯିବ ଏବଂ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ହରାଇବ।"</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ କରାଯିବ ଏବଂ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ହରାଇବ।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"ଫୋନ୍‍ ଅନଲକ୍‍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ, ଫୋନ୍‍ଟି ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ ଏବଂ ଆପଣ ସମସ୍ତ ୟୁଜର୍‍ ଡାଟା ହରାଇବେ।"</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"ଟାବଲେଟ୍‍ ଅନଲକ୍‍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଟାବଲେଟ୍‍ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। ବର୍ତ୍ତମାନ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। ବର୍ତ୍ତମାନ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"ଫୋନ୍‍ ଅନଲକ୍‍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଫୋନ୍‍ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ।"</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"ପାଟର୍ନ ଭୁଲି ଯାଇଛନ୍ତି କି?"</string>
@@ -954,7 +954,7 @@
<string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"ବ୍ରାଉଜର୍‍ରେ ଭିଜିଟ୍‍ କରାଯାଇଥିବା ସମସ୍ତ URL ପଢ଼ିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଧ୍ୟାନଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ୱେବ୍‍ ବ୍ରାଉଜ୍‍ କରିବା ଦକ୍ଷତା ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍‌ କିମ୍ବା ଅନ୍ୟାନ୍ୟ ଆପ୍ଲିକେଶନ୍‍‍ରେ ଲାଗୁ କରାଯାଇନପାରେ।"</string>
<string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"ୱେବ୍‍ ବୁକ୍‍ମାର୍କ ଓ ହିଷ୍ଟୋରୀ ଲେଖନ୍ତୁ"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"ଆପଣଙ୍କ ଟାବ୍‍ଲେଟ୍‍ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ବ୍ରାଉଜର୍‍ ହିଷ୍ଟୋରୀ କିମ୍ବା ବୁକ୍‍ମାର୍କଗୁଡ଼ିକ ବଦଳାଇବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଏହାଦ୍ୱାରା ଆପ୍‍ଟି ବ୍ରାଉଜର୍‍ ଡାଟା ଲିଭାଇପାରେ କିମ୍ବା ବଦଳାଇପାରେ। ଧ୍ୟାନଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ୱେବ୍‍ ବ୍ରାଉଜ୍‍ କରିବାର ଦକ୍ଷତା ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍‌ କିମ୍ବା ଅନ୍ୟାନ୍ୟ ଆପ୍ଲିକେଶନ୍‍‍ରେ ଲାଗୁ କରାଯାଇନପାରେ।"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"ଆପଣଙ୍କ Android ଟିଭି ଡିଭାଇସ୍ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ବ୍ରାଉଜର୍ ଇତିହାସ କିମ୍ବା ବୁକମାର୍କଗୁଡ଼ିକ ସଂଶୋଧନ ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ଦ୍ୱାରା ଆପ୍ ବ୍ରାଉଜର୍ ଡାଟା ଲିଭାଇ ପାରେ କିମ୍ବା ସଂଶୋଧନ କରିପାରେ। ଧ୍ୟାନ ଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ହୁଏତ ୱେବ୍ ବ୍ରାଉଜିଂ ଦକ୍ଷତା ସହ ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍ କିମ୍ବା ଅନ୍ୟ ଆପ୍ଲିକେସନ୍‌ରେ ଲାଗୁ କରାଯାଇ ନପାରେ।"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ବ୍ରାଉଜର୍ ଇତିହାସ କିମ୍ବା ବୁକମାର୍କଗୁଡ଼ିକୁ ସଂଶୋଧନ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ଦ୍ୱାରା ଆପ୍ ବ୍ରାଉଜର୍ ଡାଟା ଲିଭାଇ ପାରେ କିମ୍ବା ସଂଶୋଧନ କରିପାରେ। ଧ୍ୟାନ ଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ହୁଏତ ୱେବ୍ ବ୍ରାଉଜିଂ ଦକ୍ଷତା ସହ ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍ କିମ୍ବା ଅନ୍ୟ ଆପ୍ଲିକେସନ୍‌ରେ ଲାଗୁ କରାଯାଇ ନପାରେ।"</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"ଆପଣଙ୍କ ଫୋନ୍‍ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ବ୍ରାଉଜର୍‍ ହିଷ୍ଟୋରୀ କିମ୍ବା ବୁକ୍‍ମାର୍କଗୁଡ଼ିକ ବଦଳାଇବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଏହାଦ୍ୱାରା ଆପ୍‍ଟି ବ୍ରାଉଜର୍‍ ଡାଟା ଲିଭାଇପାରେ କିମ୍ବା ବଦଳାଇପାରେ। ଧ୍ୟାନଦିଅନ୍ତୁ: ଏହି ଅନୁମତି ୱେବ୍‍ ବ୍ରାଉଜ୍‍ କରିବାର ଦକ୍ଷତା ତୃତୀୟ-ପକ୍ଷ ବ୍ରାଉଜର୍‌ କିମ୍ବା ଅନ୍ୟାନ୍ୟ ଆପ୍ଲିକେଶନ୍‍‍ରେ ଲାଗୁ କରାଯାଇନପାରେ।"</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"ଏକ ଆଲର୍ମ ସେଟ୍‍ କରନ୍ତୁ"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"ଆପ୍‍କୁ, ଇନଷ୍ଟଲ୍‍ ହୋଇଥିବା ଆଲାର୍ମ କ୍ଲକ୍‍ ଆପ୍‍ରେ ଏକ ଆଲାର୍ମ ସେଟ୍‍ କରିବାକୁ ଦେଇଥାଏ। କିଛି ଆଲର୍ମ କ୍ଲକ୍ ଆପ୍‍ ଏହି ବୈଶିଷ୍ଟ୍ୟ ଲାଗୁ କରିନପାରନ୍ତି।"</string>
@@ -1609,17 +1609,16 @@
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"ଆପଣଙ୍କ ପାସ୍‌ୱର୍ଡକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଟାଇପ୍ କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ \n\nପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"ଆପଣଙ୍କ ଲକ୍‍ ଖୋଲିବା ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ \n\nପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"ଟାବଲେଟ୍‌ ଅନଲକ୍‍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ, ଟାବଲେଟ୍‌ଟି ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ ଏବଂ ସମସ୍ତ ୟୁଜର୍‍ ଡାଟା ବାହାରିଯିବ।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍ ଡିଫଲ୍ଟକୁ ଫ୍ୟାକ୍ଟୋରୀ ରିସେଟ୍ କରାଯିବ ଏବଂ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ହରାଇବ।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ କରାଯିବ ଏବଂ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ହରାଇବ।"</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"ଫୋନ୍‌ ଅନଲକ୍‍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ, ଫୋନ୍‌ଟି ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ ଏବଂ ସମସ୍ତ ୟୁଜର୍‍ ଡାଟା ବାହାରିଯିବ।"</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"ଟାବଲେଟ୍‌ ଅନଲକ୍‍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଟାବଲେଟ୍‌ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। ବର୍ତ୍ତମାନ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଭୁଲ ଭାବେ ଅନ୍‌ଲକ୍ କରିବାକୁ ଚେଷ୍ଟା କରିଛନ୍ତି। ବର୍ତ୍ତମାନ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍ ହୋଇଯିବ।"</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"ଫୋନ୍‌ ଅନଲକ୍‍ କରିବାକୁ ଆପଣ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ ପ୍ରୟାସ କଲେ। ଫୋନ୍‌ଟି ବର୍ତ୍ତମାନ ଫ୍ୟାକ୍ଟୋରୀ ଡିଫଲ୍ଟକୁ ରିସେଟ୍‍ ହୋଇଯିବ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"ଆପଣଙ୍କ ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଏକ ଇମେଲ୍‍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ନିଜ ଟାବଲେଟ୍‌କୁ ଅନଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"ଆପଣ ଆପଣଙ୍କର ଲକ୍ ଖୋଲିବା ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଆଙ୍କିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ। \n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ମଧ୍ୟରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"ଆପଣ ଆପଣଙ୍କର ଅନଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଆଙ୍କିଛନ୍ତି। <xliff:g id="NUMBER_1">%2$d</xliff:g> ଥର ଅସଫଳ ଚେଷ୍ଟା ପରେ, ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ। \n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ମଧ୍ୟରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ଆପଣଙ୍କ ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଏକ ଇମେଲ୍‍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ନିଜ ଫୋନ୍‌କୁ ଅନଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ବାହାର କରନ୍ତୁ"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"ପୃଷ୍ଠଭୂମିରେ <xliff:g id="PACKAGENAME">%1$s</xliff:g>ରୁ ଆରମ୍ଭ ହୋଇଥିବା ସମ୍ମୁଖଭାଗ ସେବା ପାଇଁ ଭବିଷ୍ୟତର R ବିଲ୍ଡଗୁଡ଼ିକରେ ବ୍ୟବହାର କରାଯିବା ସମୟରେ ଅନୁମତି ସୁବିଧା ରହିବ ନାହିଁ। ଦୟାକରି go/r-bg-fgs-restriction ଦେଖନ୍ତୁ ଏବଂ ଏକ ବଗରିପୋର୍ଟ ଫାଇଲ୍ କରନ୍ତୁ।"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ମାତ୍ରା ବଢ଼ାଇ ସୁପାରିଶ ସ୍ତର ବଢ଼ାଉଛନ୍ତି? \n\n ଲମ୍ବା ସମୟ ପର୍ଯ୍ୟନ୍ତ ଉଚ୍ଚ ଶବ୍ଦରେ ଶୁଣିଲେ ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତି ଖରାପ ହୋଇପାରେ।"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ଆକ୍ସେସବିଲିଟି ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରିବେ?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ସର୍ଟକଟ୍ ଚାଲୁ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍ ବଟନ୍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଏକ ଆକ୍ସେସବିଲିଟି ଫିଚର୍ ଆରମ୍ଭ ହେବ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 77341c677abe..9faa33785f1f 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ਹਟਾਓ"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> ਤੋਂ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਸ਼ੁਰੂ ਕੀਤੀ ਗਈ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾ ਲਈ ਭਵਿੱਖੀ R ਬਿਲਡ ਵਿੱਚ \'ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ \'ਤੇ ਇਜਾਜ਼ਤ\' ਵਿਸ਼ੇਸ਼ਤਾ ਨਹੀਂ ਹੋਵੇਗੀ। ਕਿਰਪਾ ਕਰਕੇ go/r-bg-fgs-restriction ਦੇਖੋ ਅਤੇ ਬੱਗ ਰਿਪੋਰਟ ਫ਼ਾਈਲ ਕਰੋ।"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ਕੀ ਵੌਲਿਊਮ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੇ ਪੱਧਰ ਤੋਂ ਵਧਾਉਣੀ ਹੈ?\n\nਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚ ਵੌਲਿਊਮ ਤੇ ਸੁਣਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ।"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਵਰਤਣਾ ਹੈ?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f89189b3fa9e..8fc295d525c9 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1663,7 +1663,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu danych logowania na konto Google.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Usuń"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Uruchomiona w tle usługa działająca w pierwszym planie z pakietu <xliff:g id="PACKAGENAME">%1$s</xliff:g> nie będzie miała uprawnień obowiązujących podczas używania w przyszłych kompilacjach R. Zapoznaj się z ograniczeniem go/r-bg-fgs-restriction i zgłoś błąd."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zwiększyć głośność ponad zalecany poziom?\n\nSłuchanie głośno przez długi czas może uszkodzić Twój słuch."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Użyć skrótu do ułatwień dostępu?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Gdy skrót jest włączony, jednoczesne naciskanie przez trzy sekundy obu przycisków głośności uruchamia funkcję ułatwień dostępu."</string>
@@ -1687,7 +1686,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Odmów"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Wybierz funkcję, aby zacząć z niej korzystać:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Wybierz funkcje, których chcesz używać z przyciskiem ułatwień dostępu"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Wybierz funkcje, których chcesz używać w przypadku skrótu z klawiszami głośności"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Wybierz funkcje, do których chcesz używać skrótu z klawiszami głośności"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usługa <xliff:g id="SERVICE_NAME">%s</xliff:g> została wyłączona"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edytuj skróty"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 4858b42d8acf..8173d07fb4c4 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1311,7 +1311,7 @@
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selecione para desativar a depuração USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuração por Wi-Fi conectada"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toque para desativar a depuração por Wi-Fi"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Selecione para desativar a depuração sem fio."</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Selecione para desativar a depuração por Wi-Fi."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Modo Arcabouço de testes ativado"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Realize uma redefinição para configuração original para desativar o modo Arcabouço de testes."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Console serial ativado"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"O serviço em primeiro plano iniciado em segundo plano por <xliff:g id="PACKAGENAME">%1$s</xliff:g> não receberá uma permissão durante o uso em futuras versões R. Consulte go/r-bg-fgs-restriction e crie um relatório de bug."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho estiver ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index a13c2d28f986..069dc64c0b79 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -237,7 +237,7 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Opções do telefone"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Bloqueio de ecrã"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Desligar"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Ligar/desligar"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Ligar"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Reiniciar"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Emergência"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Relatório de erros"</string>
@@ -264,7 +264,7 @@
<string name="global_action_settings" msgid="4671878836947494217">"Definições"</string>
<string name="global_action_assist" msgid="2517047220311505805">"Assistência"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"Assist. de voz"</string>
- <string name="global_action_lockdown" msgid="2475471405907902963">"Bloqueio"</string>
+ <string name="global_action_lockdown" msgid="2475471405907902963">"Bloquear"</string>
<string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999+"</string>
<string name="notification_hidden_text" msgid="2835519769868187223">"Nova notificação"</string>
<string name="notification_channel_virtual_keyboard" msgid="6465975799223304567">"Teclado virtual"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Depois de mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem sucesso, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"O serviço em primeiro plano iniciado em segundo plano de <xliff:g id="PACKAGENAME">%1$s</xliff:g> não terá a autorização durante a utilização em compilações R futuras. Aceda a go/r-bg-fgs-restriction e envie um relatório de erros."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir com um volume elevado durante longos períodos poderá ser prejudicial para a sua audição."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Pretende utilizar o atalho de acessibilidade?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho está ativado, premir ambos os botões de volume durante 3 segundos inicia uma funcionalidade de acessibilidade."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Recusar"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque numa funcionalidade para começar a utilizá-la:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha funcionalidades para utilizar com o botão Acessibilidade"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha funcionalidades para utilizar com o atalho das teclas de volume"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha funcionalidades para usar com o atalho das teclas de volume"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O serviço <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado."</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
@@ -1652,7 +1651,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correção da cor"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Prima sem soltar as teclas de volume durante três segundos para utilizar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolha uma funcionalidade para utilizar quando tocar no botão Acessibilidade:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolha a funcionalidade a utilizar com o gesto de acessibilidade (deslize rapidamente com dois dedos para cima a partir da parte inferior do ecrã):"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4858b42d8acf..8173d07fb4c4 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1311,7 +1311,7 @@
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selecione para desativar a depuração USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuração por Wi-Fi conectada"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toque para desativar a depuração por Wi-Fi"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Selecione para desativar a depuração sem fio."</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Selecione para desativar a depuração por Wi-Fi."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Modo Arcabouço de testes ativado"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Realize uma redefinição para configuração original para desativar o modo Arcabouço de testes."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Console serial ativado"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"O serviço em primeiro plano iniciado em segundo plano por <xliff:g id="PACKAGENAME">%1$s</xliff:g> não receberá uma permissão durante o uso em futuras versões R. Consulte go/r-bg-fgs-restriction e crie um relatório de bug."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho estiver ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index aeaceca65c65..4c5fbe6cec6f 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1641,7 +1641,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminați"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Serviciul în prim-plan inițializat în fundal din <xliff:g id="PACKAGENAME">%1$s</xliff:g> nu va avea permisiunea în timpul utilizării în versiunile R viitoare. Consultați go/r-bg-fgs-restriction și trimiteți un raport de eroare."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ridicați volumul mai sus de nivelul recomandat?\n\nAscultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utilizați comanda rapidă pentru accesibilitate?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Atunci când comanda rapidă este activată, dacă apăsați ambele butoane de volum timp de trei secunde, veți lansa o funcție de accesibilitate."</string>
@@ -1665,7 +1664,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Refuzați"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Atingeți o funcție ca să începeți să o folosiți:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Alegeți funcțiile pe care să le folosiți cu butonul de accesibilitate"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Alegeți funcțiile pe care să le folosiți cu comanda rapidă pentru butonul de volum"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Alegeți funcțiile pentru comanda rapidă a butonului de volum"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> a fost dezactivat"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editați comenzile rapide"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gata"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 83dd3e23c702..38fcff144a56 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -242,7 +242,7 @@
<string name="global_action_lock" msgid="6949357274257655383">"Блокировка экрана"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Выключить"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Питание"</string>
- <string name="global_action_restart" msgid="4678451019561687074">"Перезапуск"</string>
+ <string name="global_action_restart" msgid="4678451019561687074">"Перезапустить"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Экстренный вызов"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Отчет об ошибке"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Закончить сеанс"</string>
@@ -1663,7 +1663,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Вы <xliff:g id="NUMBER_0">%1$d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%2$d</xliff:g> неверных попыток для разблокировки телефона потребуется войти в аккаунт Google.\n\nПовтор через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Удалить"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Службы из пакета <xliff:g id="PACKAGENAME">%1$s</xliff:g>, переведенные из фонового режима в активный, не будут получать разрешение while-in-use в будущих сборках на языке R. Перейдите на страницу go/r-bg-fgs-restriction и отправьте отчет об ошибке."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Установить громкость выше рекомендуемого уровня?\n\nВоздействие громкого звука в течение долгого времени может привести к повреждению слуха."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Использовать быстрое включение?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Чтобы использовать функцию специальных возможностей, когда она включена, нажмите и удерживайте обе кнопки регулировки громкости в течение трех секунд."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index e61b4e8696a3..b477be89b6dc 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%2$d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ඉවත් කරන්න"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> වෙතින් පසුබිම ආරම්භ කරන ලද පෙරබිම් සේවාව අනාගත R තැනුම්වලදී භාවිතයේ අවසරය නැත. කරුණාකර go/r-bg-fgs-අවහිරතාව බලා දෝෂ වාර්තාවක් ගොනු කරන්න."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"නිර්දේශිතයි මට්ටමට වඩා ශබ්දය වැඩිද?\n\nදිගු කාලයක් සඳහා ඉහළ ශබ්දයක් ඇසීමෙන් ඇතැම් විට ඔබගේ ඇසීමට හානි විය හැක."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ප්‍රවේශ්‍යතා කෙටිමඟ භාවිතා කරන්නද?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"කෙටිමග ක්‍රියාත්මක විට, හඬ පරිමා බොත්තම් දෙකම තත්පර 3ක් තිස්සේ එබීමෙන් ප්‍රවේශ්‍යතා විශේෂාංගය ආරම්භ වනු ඇත."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index be1d8c1fef18..11c99a1f57d4 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -241,13 +241,13 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Možnosti telefónu"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Zámka obrazovky"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Vypnúť"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Vypnutie"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Vypnúť"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Reštartovať"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Tieseň"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Hlásenie o chybách"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Ukončiť reláciu"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Snímka obrazovky"</string>
- <string name="bugreport_title" msgid="8549990811777373050">"Hlásenie chyby"</string>
+ <string name="bugreport_title" msgid="8549990811777373050">"Nahlásiť chybu"</string>
<string name="bugreport_message" msgid="5212529146119624326">"Týmto zhromaždíte informácie o aktuálnom stave zariadenia. Informácie je potom možné odoslať e-mailom, chvíľu však potrvá, kým bude hlásenie chyby pripravené na odoslanie. Prosíme vás preto o trpezlivosť."</string>
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"Interaktívne nahlásenie"</string>
<string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Táto možnosť je vhodná pre väčšinu prípadov. Umožňuje sledovať priebeh nahlásenia, zadávať ďalšie podrobnosti o probléme a vytvárať snímky obrazovky. Môžu byť vynechané niektoré menej používané sekcie, ktorých nahlásenie trvá dlho."</string>
@@ -1663,12 +1663,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e-mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrániť"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Služba na popredí spustená na pozadí z balíka <xliff:g id="PACKAGENAME">%1$s</xliff:g> nebude mať v budúcich zostavách R povolenie Počas používania. Prejdite na go/r-bg-fgs-restriction a odošlite hlásenie chyby."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšiť hlasitosť nad odporúčanú úroveň?\n\nDlhodobé počúvanie pri vysokej hlasitosti môže poškodiť váš sluch."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použiť skratku dostupnosti?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Keď je skratka zapnutá, stlačením obidvoch tlačidiel hlasitosti na tri sekundy spustíte funkciu dostupnosti."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Chcete zapnúť funkcie dostupnosti?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Pridržaním oboch klávesov hlasitosti na niekoľko sekúnd zapnete funkcie dostupnosti. Môže sa tým zmeniť spôsob fungovania vášho zariadenia.\n\nAktuálne funkcie:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVybrané funkcie môžete zmeniť v časti Nastavenia &gt; Dostupnosť."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Pridržaním oboch tlačidiel hlasitosti na niekoľko sekúnd zapnete funkcie dostupnosti. Môže sa tým zmeniť spôsob fungovania vášho zariadenia.\n\nAktuálne funkcie:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVybrané funkcie môžete zmeniť v časti Nastavenia &gt; Dostupnosť."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Chcete zapnúť <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Pridržaním oboch klávesov hlasitosti na niekoľko sekúnd zapnete funkciu dostupnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Môže sa tým zmeniť spôsob fungovania vášho zariadenia.\n\nTúto skratku môžete zmeniť na inú funkciu v časti Nastavenia &gt; Dostupnosť."</string>
@@ -1695,8 +1694,8 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použiť skratku"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzia farieb"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Úprava farieb"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste klávesy hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste klávesy hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Ak chcete používať službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, pridržte tri sekundy oba klávesy hlasitosti"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Klepnutím na tlačidlo dostupnosti vyberte požadovanú funkciu:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Vyberte funkciu, ktorú chcete používať s daným gestom dostupnosti (potiahnutím dvoma prstami z dolnej časti obrazovky nahor):"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ec8bf51890a0..e21cc58dfda5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1168,7 +1168,7 @@
<string name="whichViewApplication" msgid="5733194231473132945">"Odpiranje z aplikacijo"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"Odpiranje z aplikacijo %1$s"</string>
<string name="whichViewApplicationLabel" msgid="7367556735684742409">"Odpiranje"</string>
- <string name="whichOpenHostLinksWith" msgid="7645631470199397485">"Odpiranje povezav <xliff:g id="HOST">%1$s</xliff:g> z"</string>
+ <string name="whichOpenHostLinksWith" msgid="7645631470199397485">"Odpiranje povezav <xliff:g id="HOST">%1$s</xliff:g> z aplikacijo"</string>
<string name="whichOpenLinksWith" msgid="1120936181362907258">"Odpiranje povezav z"</string>
<string name="whichOpenLinksWithApp" msgid="6917864367861910086">"Odpiranje povezav z aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
<string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"Odpiranje povezav <xliff:g id="HOST">%1$s</xliff:g> z aplikacijo <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
@@ -1663,7 +1663,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrani"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"V prihodnjih različicah R storitev v ospredju z zagonom iz ozadja iz paketa <xliff:g id="PACKAGENAME">%1$s</xliff:g> ne bo imela dovoljenja med uporabo aplikacije. Oglejte si go/r-bg-fgs-restriction in pošljite poročilo o napakah."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ali želite povečati glasnost nad priporočeno raven?\n\nDolgotrajno poslušanje pri veliki glasnosti lahko poškoduje sluh."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite uporabljati bližnjico funkcij za ljudi s posebnimi potrebami?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ko je bližnjica vklopljena, pritisnite gumba za glasnost in ju pridržite tri sekunde, če želite zagnati funkcijo za ljudi s posebnimi potrebami."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 16d7a7bb110c..156e82f56f89 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh telefonin duke përdorur një llogari mail-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hiq"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Shërbimi në plan të parë i nisur në sfond nga <xliff:g id="PACKAGENAME">%1$s</xliff:g> nuk do të ketë lejen e nevojshme gjatë përdorimit në ndërtimet e ardhshme R. Shiko go/r-bg-fgs-restriction dhe dërgo një raport të defekteve në kod."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Të ngrihet volumi mbi nivelin e rekomanduar?\n\nDëgjimi me volum të lartë për periudha të gjata mund të dëmtojë dëgjimin."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Të përdoret shkurtorja e qasshmërisë?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kur shkurtorja është e aktivizuar, shtypja e të dy butonave për 3 sekonda do të nisë një funksion qasshmërie."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b4b1523913fe..6ca87a1fb926 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1641,7 +1641,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде/и."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Уклони"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Услуга у првом плану са <xliff:g id="PACKAGENAME">%1$s</xliff:g> која је покренута у позадини неће имати дозволу током коришћења у будућим R верзијама. Посетите go/r-bg-fgs-restriction и пошаљите извештај о грешци."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Желите да појачате звук изнад препорученог нивоа?\n\nСлушање гласне музике дуже време може да вам оштети слух."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Желите ли да користите пречицу за приступачност?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Када је пречица укључена, притисните оба дугмета за јачину звука да бисте покренули функцију приступачности."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 566d85f24c08..8bbf7756b0d7 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1619,12 +1619,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök ombeds du låsa upp mobilen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ta bort"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Förgrundstjänsten från <xliff:g id="PACKAGENAME">%1$s</xliff:g> som startades i bakgrunden får inte behörighet som gäller vid användning i framtida R-versioner. Besök go/r-bg-fgs-restriction och skicka en felrapport."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vill du höja volymen över den rekommenderade nivån?\n\nAtt lyssna med stark volym långa stunder åt gången kan skada hörseln."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vill du använda Aktivera tillgänglighet snabbt?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"När kortkommandot har aktiverats startar du en tillgänglighetsfunktion genom att trycka ned båda volymknapparna i tre sekunder."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Vill du aktivera tillgänglighetsfunktionerna?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Om du trycker ned båda volymknapparna i ett par sekunder aktiveras tillgänglighetsfunktionerna. Det kan leda till att enheten fungerar annorlunda.\n\nAktuella funktioner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan ändra vilka funktioner som aktiveras under Inställningar &gt; Tillgänglighet."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Om du trycker ned båda volymknapparna i ett par sekunder aktiveras tillgänglighetsfunktionerna. Det kan få enheten ett fungera annorlunda.\n\nAktuella funktioner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan ändra vilka funktioner som aktiveras under Inställningar &gt; Tillgänglighet."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Vill du aktivera <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Om du trycker ned båda volymknapparna i ett par sekunder aktiveras <xliff:g id="SERVICE">%1$s</xliff:g>, en tillgänglighetsfunktion. Det kan leda till att enheten fungerar annorlunda.\n\nDu kan ändra vilken funktion som ska aktiveras med genvägen under Inställningar &gt; Tillgänglighet."</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Neka"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryck på funktioner som du vill aktivera:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Välj vilka funktioner du vill använda med hjälp av tillgänglighetsknappen"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Välj vilka funktioner du vill använda med hjälp av kortkommandot för volymknapparna"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Välj att funktioner att använda med hjälp av volymknappskortkommandot"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> har inaktiverats"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redigera genvägar"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klar"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f4745c6c9bfd..7a5cdcffbefa 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> yasiyofaulu, utaombwa kufungua simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ondoa"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Huduma ya programu inayotumika iliyoanzishwa chinichini kwenye <xliff:g id="PACKAGENAME">%1$s</xliff:g> haitakuwa na ruhusa inapotumika katika miundo ijayo ya R. Tafadhali angalia go/r-bg-fgs-restriction na uwasilishe ripoti ya hitilafu."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ungependa kupandisha sauti zaidi ya kiwango kinachopendekezwa?\n\nKusikiliza kwa sauti ya juu kwa muda mrefu kunaweza kuharibu uwezo wako wa kusikia."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ungependa kutumia njia ya mkato ya ufikivu?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Unapowasha kipengele cha njia ya mkato, hatua ya kubonyeza vitufe vyote viwili vya sauti kwa sekunde tatu itafungua kipengele cha ufikivu."</string>
@@ -1652,7 +1651,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ugeuzaji rangi"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Usahihishaji wa rangi"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Vitufe vya sauti vilivyoshikiliwa. Umewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vilivyoshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vimeshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Bonyeza na ushikilie vitufe vyote viwili vya sauti kwa sekunde tatu ili utumie <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Chagua kipengele utakachotumia ukigusa kitufe cha ufikivu:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Chagua kipengele cha kutumia pamoja na ishara ya ufikivu (telezesha vidole viwili kutoka chini kwenda juu kwenye skrini):"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 2eb8c87e68e1..32ea9795ed9d 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். மேலும் <xliff:g id="NUMBER_1">%2$d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, மின்னஞ்சல் கணக்கைப் பயன்படுத்தி உங்கள் மொபைலைத் திறக்கக் கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"அகற்று"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> இல் இருந்து பின்னணியில் தொடங்கப்பட்ட முன்புலச் சேவைக்கு, வரவுள்ள R பதிப்புகளில் உபயோகத்தின்போது மட்டுமான அனுமதி இருக்காது. go/r-bg-fgs-restriction என்பதைப் பார்த்து பிழை அறிக்கை ஒன்றைச் சமர்ப்பிக்கவும்."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"பரிந்துரைத்த அளவை விட ஒலியை அதிகரிக்கவா?\n\nநீண்ட நேரத்திற்கு அதிகளவில் ஒலி கேட்பது கேட்கும் திறனைப் பாதிக்கலாம்."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"அணுகல்தன்மை ஷார்ட்கட்டைப் பயன்படுத்தவா?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ஷார்ட்கட் இயக்கத்தில் இருக்கும்போது ஒலியளவு பட்டன்கள் இரண்டையும் 3 வினாடிகளுக்கு அழுத்தினால் அணுகல்தன்மை அம்சம் இயக்கப்படும்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 0251d721492a..fe392d461eba 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1311,7 +1311,7 @@
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"డీబగ్గింగ్‌ని నిలిపివేయడానికి ఎంచుకోండి."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"వైర్‌లెస్ డీబగ్గింగ్ కనెక్ట్ చేయబడింది"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"వైర్‌లెస్ డీబగ్గింగ్‌ని ఆఫ్ చేయడానికి ట్యాప్ చేయండి"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"వైర్‌లెస్ డీబగ్గింగ్‌ని డిజేబుల్ చేయడానికి ఎంచుకోండి."</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"వైర్‌లెస్ డీబగ్గింగ్‌ను డిజేబుల్ చేయడానికి ఎంచుకోండి."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"పరీక్ష నియంత్రణ మోడ్ ప్రారంభించబడింది"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"పరీక్ష నియంత్రణ మోడ్‌ను నిలిపివేయడానికి ఫ్యాక్టరీ రీసెట్‍‌ను అమలు చేయండి."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"సీరియల్ కన్సోల్ ప్రారంభించబడింది"</string>
@@ -1619,12 +1619,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"తీసివేయి"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> నుండి, బ్యాక్‌గ్రౌండ్‌లో ప్రారంభమైన ఫోర్ గ్రౌండ్ సేవకు భవిష్యత్తు R బిల్డ్స్‌లో \'ఉపయోగంలో వున్నప్పుడు\' అనుమతి ఉండదు. దయచేసి go/r-bg-fgs-restrictionను చూసి బగ్ నివేదికను ఫైల్ చేయండి."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"వాల్యూమ్‌ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్‌లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"యాక్సెస్ సామర్థ్యం షార్ట్‌కట్‌ను ఉపయోగించాలా?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"షార్ట్‌కట్ ఆన్ చేసి ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్‌లను 3 సెకన్ల పాటు నొక్కి ఉంచితే యాక్సెస్ సౌలభ్య ఫీచర్ ప్రారంభం అవుతుంది."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"యాక్సెసిబిలిటీ‌లను ఆన్ చేయాలా?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"రెండు వాల్యూమ్ కీలను కొంత సేపు నొక్కి పట్టుకోవడం ద్వారా యాక్సెసిబిలిటీలు ఆన్ అవుతాయి. ఇది మీ పరికరం పనిచేసే విధానాన్ని మార్చవచ్చు.\n\nప్రస్తుత ఫీచర్లు:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nఎంపిక చేసిన ఫీచర్లను మీరు సెట్టింగ్‌లు&gt;యాక్సెసిబిలిటీలో మార్చవచ్చు."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"రెండు వాల్యూమ్ కీలను కొంత సేపు నొక్కి పట్టుకుంటే యాక్సెసిబిలిటీలు ఆన్ అవుతాయి. ఇది మీ పరికరం పనిచేసే విధానాన్ని మార్చవచ్చు.\n\nప్రస్తుత ఫీచర్లు:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nఎంపిక చేసిన ఫీచర్లను మీరు సెట్టింగ్‌లు&gt;యాక్సెసిబిలిటీలో మార్చవచ్చు."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> ఆన్ చేయాాలా?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"రెండు వాల్యూమ్ కీలను కొన్ని సెకన్ల పాటు నొక్కి పట్టుకోవడం ద్వారా యాక్సెసిబిలిటీ అయిన <xliff:g id="SERVICE">%1$s</xliff:g> ఆన్ అవుతుంది. ఇది మీ పరికరం పని చేసే విధానాన్ని మార్చవచ్చు.\n\nసెట్టింగ్‌లు &gt; యాక్సెసిబిలిటీలో, వేరొక ఫీచర్‌ను ప్రారంభించేలా ఈ షార్ట్ కట్‌ను మీరు మార్చవచ్చు."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 683b22fa7396..000ad10827a4 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1309,7 +1309,7 @@
<string name="adb_active_notification_title" msgid="408390247354560331">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"แตะเพื่อปิดการแก้ไขข้อบกพร่อง USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"เลือกเพื่อปิดใช้งานการแก้ไขข้อบกพร่อง USB"</string>
- <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"เชื่อมต่อการแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
+ <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"เชื่อมต่อการแก้ไขข้อบกพร่องผ่าน Wi-Fi แล้ว"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"แตะเพื่อปิดการแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"เลือกเพื่อปิดใช้การแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"โหมดโปรแกรมทดสอบอัตโนมัติเปิดใช้อยู่"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ลบ"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"บริการที่ทำงานอยู่เบื้องหน้าซึ่งเริ่มขึ้นในเบื้องหลังจาก <xliff:g id="PACKAGENAME">%1$s</xliff:g> จะไม่มีสิทธิ์ขณะใช้งานใน R บิลด์ต่อๆ ไป โปรดดู go/r-bg-fgs-restriction และส่งรายงานข้อบกพร่อง"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"นี่เป็นการเพิ่มระดับเสียงเกินระดับที่แนะนำ\n\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ใช้ทางลัดการช่วยเหลือพิเศษไหม"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มนาน 3 วินาทีจะเริ่มฟีเจอร์การช่วยเหลือพิเศษ"</string>
@@ -1650,7 +1649,7 @@
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ปิดทางลัด"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ใช้ทางลัด"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"การกลับสี"</string>
- <string name="color_correction_feature_name" msgid="3655077237805422597">"การปรับแก้สี"</string>
+ <string name="color_correction_feature_name" msgid="3655077237805422597">"การแก้สี"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว เปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว ปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 3 วินาทีเพื่อใช้ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index b7e8b9a94e30..f2ee40453df8 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukang muli sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alisin"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Ang sinimulan sa background na serbisyo sa foreground mula sa <xliff:g id="PACKAGENAME">%1$s</xliff:g> ay hindi magkakaroon ng pahintulot habang ginagamit sa mga R build sa hinaharap. Pakipuntahan ang go/r-bg-fgs-restriction at maghain ng bugreport."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lakasan ang volume nang lagpas sa inirerekomendang antas?\n\nMaaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gagamitin ang Shortcut sa Accessibility?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index f3b5a63e78fa..19bdba898eb9 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız denemeden sonra telefonunuzu bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kaldır"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"<xliff:g id="PACKAGENAME">%1$s</xliff:g> paketinden ön plan hizmetini başlatan arka plan, sonraki R derlemelerinde kullanım sırasında iznine sahip olmayacak. Lütfen go/r-bg-fgs-restriction sayfasına bakıp hata raporu girin."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ses seviyesi önerilen düzeyin üzerine yükseltilsin mi?\n\nUzun süre yüksek ses seviyesinde dinlemek işitme duyunuza zarar verebilir."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erişilebilirlik Kısayolu Kullanılsın mı?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kısayol açıkken ses düğmelerinin ikisini birden 3 saniyeliğine basılı tutmanız bir erişilebilirlik özelliğini başlatır."</string>
@@ -1652,7 +1651,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"Rengi Ters Çevirme"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Renk Düzeltme"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> açıldı."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tutun. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini kullanmak için her iki ses tuşunu basılı tutun"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Erişilebilirlik düğmesine dokunduğunuzda kullanmak için bir özellik seçin:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Erişilebilirlik hareketiyle (iki parmakla ekranın altından yukarı kaydırma) kullanılacak bir özellik seçin:"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 6b24d83e7038..04bb1cc33c61 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1349,9 +1349,9 @@
<string name="adb_active_notification_title" msgid="408390247354560331">"Налагодження USB підключено"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"Торкніться, щоб вимкнути налагодження через USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Виберіть, щоб вимкнути налагодження за USB"</string>
- <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Налагодження через Wi-Fi активне"</string>
+ <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Активне налагодження через Wi-Fi"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Натисніть, щоб вимкнути налагодження через Wi-Fi"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Виберіть, щоб вимкнути налагодження через Wi-Fi."</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Натисніть, щоб вимкнути налагодження."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Увімкнено режим автоматизованого тестування"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Щоб вимкнути режим автоматизованого тестування, відновіть заводські налаштування."</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"Послідовну консоль увімкнено"</string>
@@ -1663,12 +1663,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з’явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Вилучити"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Активний сервіс пакета <xliff:g id="PACKAGENAME">%1$s</xliff:g>, запущений у фоновому режимі, не матиме дозволу \"Коли додаток використовується\" в майбутніх складаннях R. Перегляньте go/r-bg-fgs-restriction і надішліть звіт про помилки."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Збільшити гучність понад рекомендований рівень?\n\nЯкщо слухати надто гучну музику тривалий час, можна пошкодити слух."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Використовувати швидке ввімкнення?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Якщо цей засіб увімкнено, ви можете активувати спеціальні можливості, утримуючи обидві кнопки гучності протягом трьох секунд."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Увімкнути спеціальні можливості?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Якщо втримувати обидві клавіші гучності впродовж кількох секунд, буде ввімкнено спеціальні можливості. Це може вплинути на роботу пристрою.\n\nПоточні функції:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nВибрані функції можна змінити в меню \"Налаштування &gt; Спеціальні можливості\"."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Якщо втримувати обидві клавіші гучності впродовж кількох секунд, вмикаються спеціальні можливості. Це впливає на роботу пристрою.\n\nПоточні функції:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nВибрані функції можна змінити в налаштуваннях у меню спеціальних можливостей."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Увімкнути <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Якщо втримувати обидві клавіші гучності впродовж кількох секунд, буде ввімкнено спеціальні можливості – <xliff:g id="SERVICE">%1$s</xliff:g>. Це може вплинути на роботу пристрою.\n\nДля цієї комбінації клавіш можна вибрати іншу функцію в меню \"Налаштування &gt; Спеціальні можливості\"."</string>
@@ -1820,7 +1819,7 @@
<string name="restr_pin_try_later" msgid="5897719962541636727">"Спробуйте пізніше"</string>
<string name="immersive_cling_title" msgid="2307034298721541791">"Перегляд на весь екран"</string>
<string name="immersive_cling_description" msgid="7092737175345204832">"Щоб вийти, проведіть пальцем зверху вниз."</string>
- <string name="immersive_cling_positive" msgid="7047498036346489883">"Зрозуміло"</string>
+ <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="done_label" msgid="7283767013231718521">"Готово"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Вибір годин на циферблаті"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Вибір хвилин на циферблаті"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index b432f80fce0e..8a2ead41cdef 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1311,7 +1311,7 @@
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"‏USB ڈیبگ کرنے کو غیر فعال کرنے کیلئے منتخب کریں۔"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"وائرلیس ڈیبگنگ منسلک ہے"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"وائرلیس ڈیبگنگ آف کرنے کے لیے تھپتھپائیں"</string>
- <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"وائرلیس ڈیبگنگ کرنے کو غیر فعال کرنے کے ليے منتخب کریں۔"</string>
+ <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"وائرلیس ڈیبگنگ کو غیر فعال کرنے کے ليے منتخب کریں۔"</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"ٹیسٹ ہارنیس موڈ فعال ہے"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"ٹیسٹ ہارنیس موڈ غیر فعال کرنے کے لیے فیکٹری ری سیٹ کریں۔"</string>
<string name="console_running_notification_title" msgid="6087888939261635904">"شمار کونسول فعال ہے"</string>
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کرکے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ہٹائیں"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"‏پس منظر <xliff:g id="PACKAGENAME">%1$s</xliff:g> سے شروع کی گئی پیش منظر کی سروس کو مستقبل کے R بلڈز میں استعمال کے دوران اجازت نہیں ہوگی۔ براہ کرم go/r-bg-fgs-restriction دیکھیں اور بگ رپورٹ دائر کریں۔"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"والیوم کو تجویز کردہ سطح سے زیادہ کریں؟\n\nزیادہ وقت تک اونچی آواز میں سننے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ایکسیسبیلٹی شارٹ کٹ استعمال کریں؟"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"شارٹ کٹ آن ہونے پر، 3 سیکنڈ تک دونوں والیوم بٹنز کو دبانے سے ایک ایکسیسبیلٹی خصوصیت شروع ہو جائے گی۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index fffa26553312..89550ae0f145 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Olib tashlash"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Fonda faol <xliff:g id="PACKAGENAME">%1$s</xliff:g> xizmatini ishga tushirish uchun kelgusi R nashrlarida ishlatilayotganda ruxsat berish imkoniyati boʻlmaydi. go/r-bg-fgs-restriction sahifasiga kiring va xatolik hisobotini yuboring."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Tovush balandligi tavsiya etilgan darajadan ham yuqori qilinsinmi?\n\nUzoq vaqt davomida baland ovozda tinglash eshitish qobiliyatingizga salbiy ta’sir ko‘rsatishi mumkin."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Tezkor ishga tushirishdan foydalanilsinmi?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Maxsus imkoniyatlar funksiyasidan foydalanish uchun u yoniqligida ikkala tovush tugmasini 3 soniya bosib turing."</string>
@@ -1641,9 +1640,9 @@
<string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Ilova yoki qurilma sensori bilan munosabatlaringizni kuzatishi hamda sizning nomingizdan ilovalar bilan ishlashi mumkin."</string>
<string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Ruxsat"</string>
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Rad etish"</string>
- <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Funksiyadan foydalanish uchun ustiga bosing:"</string>
+ <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Kerakli funksiyani tanlang"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Maxsus imkoniyatlar tugmasi bilan foydalanish uchun funksiyalarni tanlang"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Tovush balandligi tugmasi bilan foydalanish uchun funksiyalarni tanlang"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Tovush tugmasi bilan ishga tushiriladigan funksiyalarni tanlang"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> faolsizlantirildi"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Tezkor tugmalarni tahrirlash"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7ecad59d4162..f53c161cbd0c 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Bạn đã <xliff:g id="NUMBER_0">%1$d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Vui lòng thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Xóa"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Dịch vụ trên nền trước đã bắt đầu ở nền từ <xliff:g id="PACKAGENAME">%1$s</xliff:g> sẽ không có quyền khi đang sử dụng trong các bản dựng R trong tương lai. Vui lòng xem go/r-bg-fgs-restriction và gửi báo cáo lỗi."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bạn tăng âm lượng lên quá mức khuyên dùng?\n\nViệc nghe ở mức âm lượng cao trong thời gian dài có thể gây tổn thương thính giác của bạn."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sử dụng phím tắt Hỗ trợ tiếp cận?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Khi phím tắt này đang bật, thao tác nhấn cả hai nút âm lượng trong 3 giây sẽ mở tính năng hỗ trợ tiếp cận."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 6e2b78b0de93..a4d60e6a25df 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"删除"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"在未来的 R 版本中,在后台启动的 <xliff:g id="PACKAGENAME">%1$s</xliff:g> 中的前台服务将不具有仅在使用时授予的权限。请访问 go/r-bg-fgs-restriction 并提交错误报告。"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要将音量调高到建议的音量以上吗?\n\n长时间保持高音量可能会损伤听力。"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用无障碍快捷方式吗?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"启用这项快捷方式后,同时按下两个音量按钮 3 秒钟即可启动无障碍功能。"</string>
@@ -1651,8 +1650,8 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快捷方式"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"颜色反转"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
- <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已关闭。"</string>
+ <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已关闭。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同时按住两个音量键 3 秒钟即可使用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"选择点按“无障碍”按钮后要使用的功能:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"选择要搭配无障碍手势(用两根手指从屏幕底部向上滑动)使用的功能:"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index f808f900cdc0..458c3619c02f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1619,11 +1619,10 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解開上鎖的手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"從「<xliff:g id="PACKAGENAME">%1$s</xliff:g>」啟動前景服務的背景將不會在未來的 R 版本中提供「僅在使用此應用程式時允許」權限。請參閱 go/r-bg-fgs-restriction,提交錯誤報告。"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量 (比建議的音量更大聲) 嗎?\n\n長時間聆聽高分貝音量可能會導致您的聽力受損。"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙功能快速鍵嗎?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"啟用快速鍵後,同時按住音量按鈕 3 秒便可啟用無障礙功能。"</string>
- <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"要啟用無障礙功能嗎?"</string>
+ <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"要開啟無障礙功能嗎?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同時按下兩個音量鍵幾秒,以開啟無障礙功能。這可能會變更裝置的運作。\n\n目前功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n您可在「設定」&gt;「無障礙功能」中變更所選功能。"</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"要啟用 <xliff:g id="SERVICE">%1$s</xliff:g> 嗎?"</string>
@@ -1643,7 +1642,7 @@
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"拒絕"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"輕按即可開始使用所需功能:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"選擇要配搭無障礙功能按鈕使用的功能"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"選擇要配搭音量快速鍵使用的功能"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"選擇要用音量快速鍵的功能"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> 已關閉"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 559e681b178c..69358d44d737 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1619,12 +1619,11 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統就會要求你透過電子郵件帳戶解除手機的鎖定狀態。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"來自「<xliff:g id="PACKAGENAME">%1$s</xliff:g>」的背景啟動前景服務不會具備未來 R 版本的使用狀態權限。請前往 go/r-bg-fgs-restriction 並提交錯誤報告。"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量,比建議的音量更大聲嗎?\n\n長時間聆聽高分貝音量可能會使你的聽力受損。"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙捷徑嗎?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"啟用捷徑功能,只要同時按下兩個音量按鈕 3 秒,就能啟動無障礙功能。"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"要開啟無障礙功能嗎?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同時按住音量調高鍵和調低鍵數秒,即可開啟無障礙功能。這麼做可能會改變裝置的運作方式。\n\n目前的功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n你可以在 [設定] &gt; [無障礙設定] 中變更所選功能。"</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同時按住音量調高鍵和調低鍵數秒,即可開啟無障礙功能。這麼做可能會改變裝置的運作方式。\n\n目前的功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n你可以在 [設定] &gt; [無障礙設定] 中變更選取的功能。"</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"要開啟「<xliff:g id="SERVICE">%1$s</xliff:g>」嗎?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"同時按住音量調高鍵和調低鍵數秒,即可開啟「<xliff:g id="SERVICE">%1$s</xliff:g>」無障礙功能。這麼做可能會改變裝置的運作方式。\n\n你可以在 [設定] &gt; [無障礙設定] 中變更這個快速鍵觸發的功能。"</string>
@@ -1919,7 +1918,7 @@
<string name="app_category_social" msgid="2278269325488344054">"社交和通訊"</string>
<string name="app_category_news" msgid="1172762719574964544">"新聞和雜誌"</string>
<string name="app_category_maps" msgid="6395725487922533156">"地圖和導航"</string>
- <string name="app_category_productivity" msgid="1844422703029557883">"生產應用"</string>
+ <string name="app_category_productivity" msgid="1844422703029557883">"工作效率"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"裝置儲存空間"</string>
<string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB 偵錯"</string>
<string name="time_picker_hour_label" msgid="4208590187662336864">"點"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 3b95ffb497ba..4abd4404842c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1619,7 +1619,6 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> amasekhondi."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Susa"</string>
- <string name="allow_while_in_use_permission_in_fgs" msgid="4101339676785053656">"Ingemuva eqalise isevisi yasemuva kusuka ku-<xliff:g id="PACKAGENAME">%1$s</xliff:g> ngeke ithole imvume yokusebenzisa yesikhathi ekwakheni kwe-R ezayo. Sicela ubone i-go/r-bg-fgs-restriction bese ufayele umbiko wesiphazamiso."</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Khuphukisa ivolumu ngaphezu kweleveli enconyiwe?\n\nUkulalela ngevolumu ephezulu izikhathi ezide kungahle kulimaze ukuzwa kwakho."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sebenzisa isinqamuleli sokufinyelela?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Uma isinqamuleli sivuliwe, ukucindezela zombili izinkinobho zevolumu amasekhondi angu-3 kuzoqalisa isici sokufinyelela."</string>
diff --git a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch.apk b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v1.apk
index 1dc1e998f1ee..add4aa038708 100644
--- a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch.apk
+++ b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v1.apk
Binary files differ
diff --git a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v2.apk b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v2.apk
new file mode 100644
index 000000000000..e55eb903c68b
--- /dev/null
+++ b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v2.apk
Binary files differ
diff --git a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v3.apk b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v3.apk
new file mode 100644
index 000000000000..de2355822093
--- /dev/null
+++ b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-apk-hash-mismatch-v3.apk
Binary files differ
diff --git a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-certificate-mismatch.apk b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-certificate-mismatch.apk
index 562805cf67eb..f1105f96664c 100644
--- a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-certificate-mismatch.apk
+++ b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-certificate-mismatch.apk
Binary files differ
diff --git a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-malformed-signature.apk b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-malformed-signature.apk
index 2723cc8fdbeb..d28774aa2b14 100644
--- a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-malformed-signature.apk
+++ b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-malformed-signature.apk
Binary files differ
diff --git a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-without-block.apk b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-without-block.apk
index 9dec2f591133..604fe6f43523 100644
--- a/core/tests/coretests/assets/SourceStampVerifierTest/stamp-without-block.apk
+++ b/core/tests/coretests/assets/SourceStampVerifierTest/stamp-without-block.apk
Binary files differ
diff --git a/core/tests/coretests/assets/SourceStampVerifierTest/valid-stamp.apk b/core/tests/coretests/assets/SourceStampVerifierTest/valid-stamp.apk
index 8056e0bf6e50..2f2a5923d24a 100644
--- a/core/tests/coretests/assets/SourceStampVerifierTest/valid-stamp.apk
+++ b/core/tests/coretests/assets/SourceStampVerifierTest/valid-stamp.apk
Binary files differ
diff --git a/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java b/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java
index 37b2817928aa..81d54b57486c 100644
--- a/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java
+++ b/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java
@@ -26,8 +26,11 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import android.content.Context;
-import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
+import libcore.io.Streams;
+
+import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -46,8 +49,20 @@ import java.util.zip.ZipFile;
@RunWith(JUnit4.class)
public class SourceStampVerifierTest {
- private final Context mContext =
- InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+
+ private File mPrimaryApk;
+ private File mSecondaryApk;
+
+ @After
+ public void tearDown() throws Exception {
+ if (mPrimaryApk != null) {
+ mPrimaryApk.delete();
+ }
+ if (mSecondaryApk != null) {
+ mSecondaryApk.delete();
+ }
+ }
@Test
public void testSourceStamp_noStamp() throws Exception {
@@ -63,17 +78,11 @@ public class SourceStampVerifierTest {
@Test
public void testSourceStamp_correctSignature() throws Exception {
- File testApk = getApk("SourceStampVerifierTest/valid-stamp.apk");
- ZipFile apkZipFile = new ZipFile(testApk);
- ZipEntry stampCertZipEntry = apkZipFile.getEntry("stamp-cert-sha256");
- int size = (int) stampCertZipEntry.getSize();
- byte[] expectedStampCertHash = new byte[size];
- try (InputStream inputStream = apkZipFile.getInputStream(stampCertZipEntry)) {
- inputStream.read(expectedStampCertHash);
- }
+ mPrimaryApk = getApk("SourceStampVerifierTest/valid-stamp.apk");
+ byte[] expectedStampCertHash = getSourceStampCertificateHashFromApk(mPrimaryApk);
SourceStampVerificationResult result =
- SourceStampVerifier.verify(testApk.getAbsolutePath());
+ SourceStampVerifier.verify(mPrimaryApk.getAbsolutePath());
assertTrue(result.isPresent());
assertTrue(result.isVerified());
@@ -85,10 +94,10 @@ public class SourceStampVerifierTest {
@Test
public void testSourceStamp_signatureMissing() throws Exception {
- File testApk = getApk("SourceStampVerifierTest/stamp-without-block.apk");
+ mPrimaryApk = getApk("SourceStampVerifierTest/stamp-without-block.apk");
SourceStampVerificationResult result =
- SourceStampVerifier.verify(testApk.getAbsolutePath());
+ SourceStampVerifier.verify(mPrimaryApk.getAbsolutePath());
assertTrue(result.isPresent());
assertFalse(result.isVerified());
@@ -97,10 +106,10 @@ public class SourceStampVerifierTest {
@Test
public void testSourceStamp_certificateMismatch() throws Exception {
- File testApk = getApk("SourceStampVerifierTest/stamp-certificate-mismatch.apk");
+ mPrimaryApk = getApk("SourceStampVerifierTest/stamp-certificate-mismatch.apk");
SourceStampVerificationResult result =
- SourceStampVerifier.verify(testApk.getAbsolutePath());
+ SourceStampVerifier.verify(mPrimaryApk.getAbsolutePath());
assertTrue(result.isPresent());
assertFalse(result.isVerified());
@@ -108,11 +117,35 @@ public class SourceStampVerifierTest {
}
@Test
- public void testSourceStamp_apkHashMismatch() throws Exception {
- File testApk = getApk("SourceStampVerifierTest/stamp-apk-hash-mismatch.apk");
+ public void testSourceStamp_apkHashMismatch_v1SignatureScheme() throws Exception {
+ mPrimaryApk = getApk("SourceStampVerifierTest/stamp-apk-hash-mismatch-v1.apk");
SourceStampVerificationResult result =
- SourceStampVerifier.verify(testApk.getAbsolutePath());
+ SourceStampVerifier.verify(mPrimaryApk.getAbsolutePath());
+
+ assertTrue(result.isPresent());
+ assertFalse(result.isVerified());
+ assertNull(result.getCertificate());
+ }
+
+ @Test
+ public void testSourceStamp_apkHashMismatch_v2SignatureScheme() throws Exception {
+ mPrimaryApk = getApk("SourceStampVerifierTest/stamp-apk-hash-mismatch-v2.apk");
+
+ SourceStampVerificationResult result =
+ SourceStampVerifier.verify(mPrimaryApk.getAbsolutePath());
+
+ assertTrue(result.isPresent());
+ assertFalse(result.isVerified());
+ assertNull(result.getCertificate());
+ }
+
+ @Test
+ public void testSourceStamp_apkHashMismatch_v3SignatureScheme() throws Exception {
+ mPrimaryApk = getApk("SourceStampVerifierTest/stamp-apk-hash-mismatch-v3.apk");
+
+ SourceStampVerificationResult result =
+ SourceStampVerifier.verify(mPrimaryApk.getAbsolutePath());
assertTrue(result.isPresent());
assertFalse(result.isVerified());
@@ -121,10 +154,10 @@ public class SourceStampVerifierTest {
@Test
public void testSourceStamp_malformedSignature() throws Exception {
- File testApk = getApk("SourceStampVerifierTest/stamp-malformed-signature.apk");
+ mPrimaryApk = getApk("SourceStampVerifierTest/stamp-malformed-signature.apk");
SourceStampVerificationResult result =
- SourceStampVerifier.verify(testApk.getAbsolutePath());
+ SourceStampVerifier.verify(mPrimaryApk.getAbsolutePath());
assertTrue(result.isPresent());
assertFalse(result.isVerified());
@@ -133,21 +166,14 @@ public class SourceStampVerifierTest {
@Test
public void testSourceStamp_multiApk_validStamps() throws Exception {
- File testApk1 = getApk("SourceStampVerifierTest/valid-stamp.apk");
- File testApk2 = getApk("SourceStampVerifierTest/valid-stamp.apk");
- ZipFile apkZipFile = new ZipFile(testApk1);
- ZipEntry stampCertZipEntry = apkZipFile.getEntry("stamp-cert-sha256");
- int size = (int) stampCertZipEntry.getSize();
- byte[] expectedStampCertHash = new byte[size];
- try (InputStream inputStream = apkZipFile.getInputStream(stampCertZipEntry)) {
- inputStream.read(expectedStampCertHash);
- }
+ mPrimaryApk = getApk("SourceStampVerifierTest/valid-stamp.apk");
+ mSecondaryApk = getApk("SourceStampVerifierTest/valid-stamp.apk");
+ byte[] expectedStampCertHash = getSourceStampCertificateHashFromApk(mPrimaryApk);
List<String> apkFiles = new ArrayList<>();
- apkFiles.add(testApk1.getAbsolutePath());
- apkFiles.add(testApk2.getAbsolutePath());
+ apkFiles.add(mPrimaryApk.getAbsolutePath());
+ apkFiles.add(mSecondaryApk.getAbsolutePath());
- SourceStampVerificationResult result =
- SourceStampVerifier.verify(apkFiles);
+ SourceStampVerificationResult result = SourceStampVerifier.verify(apkFiles);
assertTrue(result.isPresent());
assertTrue(result.isVerified());
@@ -159,14 +185,13 @@ public class SourceStampVerifierTest {
@Test
public void testSourceStamp_multiApk_invalidStamps() throws Exception {
- File testApk1 = getApk("SourceStampVerifierTest/valid-stamp.apk");
- File testApk2 = getApk("SourceStampVerifierTest/stamp-apk-hash-mismatch.apk");
+ mPrimaryApk = getApk("SourceStampVerifierTest/valid-stamp.apk");
+ mSecondaryApk = getApk("SourceStampVerifierTest/stamp-apk-hash-mismatch-v3.apk");
List<String> apkFiles = new ArrayList<>();
- apkFiles.add(testApk1.getAbsolutePath());
- apkFiles.add(testApk2.getAbsolutePath());
+ apkFiles.add(mPrimaryApk.getAbsolutePath());
+ apkFiles.add(mSecondaryApk.getAbsolutePath());
- SourceStampVerificationResult result =
- SourceStampVerifier.verify(apkFiles);
+ SourceStampVerificationResult result = SourceStampVerifier.verify(apkFiles);
assertTrue(result.isPresent());
assertFalse(result.isVerified());
@@ -174,10 +199,16 @@ public class SourceStampVerifierTest {
}
private File getApk(String apkPath) throws IOException {
- File testApk = File.createTempFile("SourceStampApk", ".apk");
+ File apk = File.createTempFile("SourceStampApk", ".apk");
try (InputStream inputStream = mContext.getAssets().open(apkPath)) {
- Files.copy(inputStream, testApk.toPath(), REPLACE_EXISTING);
+ Files.copy(inputStream, apk.toPath(), REPLACE_EXISTING);
}
- return testApk;
+ return apk;
+ }
+
+ private byte[] getSourceStampCertificateHashFromApk(File apk) throws IOException {
+ ZipFile apkZipFile = new ZipFile(apk);
+ ZipEntry stampCertZipEntry = apkZipFile.getEntry("stamp-cert-sha256");
+ return Streams.readFully(apkZipFile.getInputStream(stampCertZipEntry));
}
}
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index d6542de91e08..e5492714b29f 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -129,6 +129,13 @@ prebuilt_etc {
}
prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.companiondevicesupport",
+ sub_dir: "permissions",
+ src: "com.android.car.companiondevicesupport.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_com.google.android.car.kitchensink",
sub_dir: "permissions",
src: "com.google.android.car.kitchensink.xml",
diff --git a/data/etc/car/com.android.car.companiondevicesupport.xml b/data/etc/car/com.android.car.companiondevicesupport.xml
new file mode 100644
index 000000000000..2067bab20d3d
--- /dev/null
+++ b/data/etc/car/com.android.car.companiondevicesupport.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.companiondevicesupport">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.PROVIDE_TRUST_AGENT"/>
+ <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 9b503eba5c68..8520fffb3444 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -233,6 +233,7 @@ applications that come with the platform
<!-- Permissions required for reading and logging compat changes -->
<permission name="android.permission.LOG_COMPAT_CHANGE" />
<permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+ <permission name="android.permission.REGISTER_STATS_PULL_ATOM" />
</privapp-permissions>
<privapp-permissions package="com.android.providers.telephony">
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 9d0fe11be46b..88b614dc7eef 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -483,14 +483,14 @@ public class KeyStore {
mBinder.asBinder().linkToDeath(promise, 0);
int errorCode = mBinder.addRngEntropy(promise, data, flags);
if (errorCode == NO_ERROR) {
- return promise.getFuture().get().getErrorCode() == NO_ERROR;
+ return interruptedPreservingGet(promise.getFuture()).getErrorCode() == NO_ERROR;
} else {
return false;
}
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "AddRngEntropy completed with exception", e);
return false;
} finally {
@@ -548,7 +548,7 @@ public class KeyStore {
private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
int flags, KeyCharacteristics outCharacteristics)
- throws RemoteException, ExecutionException, InterruptedException {
+ throws RemoteException, ExecutionException {
KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
int error = NO_ERROR;
KeyCharacteristicsCallbackResult result = null;
@@ -559,7 +559,7 @@ public class KeyStore {
Log.e(TAG, "generateKeyInternal failed on request " + error);
return error;
}
- result = promise.getFuture().get();
+ result = interruptedPreservingGet(promise.getFuture());
} finally {
mBinder.asBinder().unlinkToDeath(promise, 0);
}
@@ -592,7 +592,7 @@ public class KeyStore {
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "generateKey completed with exception", e);
return SYSTEM_ERROR;
}
@@ -614,7 +614,7 @@ public class KeyStore {
int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
if (error != NO_ERROR) return error;
- KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture());
error = result.getKeystoreResponse().getErrorCode();
if (error != NO_ERROR) return error;
@@ -625,7 +625,7 @@ public class KeyStore {
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
return SYSTEM_ERROR;
} finally {
@@ -640,14 +640,14 @@ public class KeyStore {
private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
int uid, int flags, KeyCharacteristics outCharacteristics)
- throws RemoteException, ExecutionException, InterruptedException {
+ throws RemoteException, ExecutionException {
KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
mBinder.asBinder().linkToDeath(promise, 0);
try {
int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
if (error != NO_ERROR) return error;
- KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture());
error = result.getKeystoreResponse().getErrorCode();
if (error != NO_ERROR) return error;
@@ -675,7 +675,7 @@ public class KeyStore {
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "ImportKey completed with exception", e);
return SYSTEM_ERROR;
}
@@ -747,7 +747,7 @@ public class KeyStore {
String wrappingKeyAlias,
byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
KeyCharacteristics outCharacteristics)
- throws RemoteException, ExecutionException, InterruptedException {
+ throws RemoteException, ExecutionException {
KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
mBinder.asBinder().linkToDeath(promise, 0);
try {
@@ -755,7 +755,7 @@ public class KeyStore {
wrappingKeyAlias, maskingKey, args, rootSid, fingerprintSid);
if (error != NO_ERROR) return error;
- KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture());
error = result.getKeystoreResponse().getErrorCode();
if (error != NO_ERROR) return error;
@@ -786,7 +786,7 @@ public class KeyStore {
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "ImportWrappedKey completed with exception", e);
return SYSTEM_ERROR;
}
@@ -818,14 +818,14 @@ public class KeyStore {
appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
if (error == NO_ERROR) {
- return promise.getFuture().get();
+ return interruptedPreservingGet(promise.getFuture());
} else {
return new ExportResult(error);
}
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "ExportKey completed with exception", e);
return null;
} finally {
@@ -864,14 +864,14 @@ public class KeyStore {
int errorCode = mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
entropy, uid);
if (errorCode == NO_ERROR) {
- return promise.getFuture().get();
+ return interruptedPreservingGet(promise.getFuture());
} else {
return new OperationResult(errorCode);
}
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "Begin completed with exception", e);
return null;
} finally {
@@ -894,14 +894,14 @@ public class KeyStore {
input = input != null ? input : new byte[0];
int errorCode = mBinder.update(promise, token, arguments, input);
if (errorCode == NO_ERROR) {
- return promise.getFuture().get();
+ return interruptedPreservingGet(promise.getFuture());
} else {
return new OperationResult(errorCode);
}
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "Update completed with exception", e);
return null;
} finally {
@@ -930,14 +930,14 @@ public class KeyStore {
signature = signature != null ? signature : new byte[0];
int errorCode = mBinder.finish(promise, token, arguments, input, signature, entropy);
if (errorCode == NO_ERROR) {
- return promise.getFuture().get();
+ return interruptedPreservingGet(promise.getFuture());
} else {
return new OperationResult(errorCode);
}
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "Finish completed with exception", e);
return null;
} finally {
@@ -972,14 +972,14 @@ public class KeyStore {
mBinder.asBinder().linkToDeath(promise, 0);
int errorCode = mBinder.abort(promise, token);
if (errorCode == NO_ERROR) {
- return promise.getFuture().get().getErrorCode();
+ return interruptedPreservingGet(promise.getFuture()).getErrorCode();
} else {
return errorCode;
}
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "Abort completed with exception", e);
return SYSTEM_ERROR;
} finally {
@@ -1135,7 +1135,7 @@ public class KeyStore {
}
int error = mBinder.attestKey(promise, alias, params);
if (error != NO_ERROR) return error;
- KeyAttestationCallbackResult result = promise.getFuture().get();
+ KeyAttestationCallbackResult result = interruptedPreservingGet(promise.getFuture());
error = result.getKeystoreResponse().getErrorCode();
if (error == NO_ERROR) {
outChain.shallowCopyFrom(result.getCertificateChain());
@@ -1144,7 +1144,7 @@ public class KeyStore {
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "AttestKey completed with exception", e);
return SYSTEM_ERROR;
} finally {
@@ -1164,7 +1164,7 @@ public class KeyStore {
}
int error = mBinder.attestDeviceIds(promise, params);
if (error != NO_ERROR) return error;
- KeyAttestationCallbackResult result = promise.getFuture().get();
+ KeyAttestationCallbackResult result = interruptedPreservingGet(promise.getFuture());
error = result.getKeystoreResponse().getErrorCode();
if (error == NO_ERROR) {
outChain.shallowCopyFrom(result.getCertificateChain());
@@ -1173,7 +1173,7 @@ public class KeyStore {
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
- } catch (ExecutionException | InterruptedException e) {
+ } catch (ExecutionException e) {
Log.e(TAG, "AttestDevicdeIds completed with exception", e);
return SYSTEM_ERROR;
} finally {
@@ -1387,4 +1387,20 @@ public class KeyStore {
int errorCode) {
return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
}
+
+ private static <R> R interruptedPreservingGet(CompletableFuture<R> future)
+ throws ExecutionException {
+ boolean wasInterrupted = false;
+ while (true) {
+ try {
+ R result = future.get();
+ if (wasInterrupted) {
+ Thread.currentThread().interrupt();
+ }
+ return result;
+ } catch (InterruptedException e) {
+ wasInterrupted = true;
+ }
+ }
+ }
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index e199cf49db9a..93fe06ac99aa 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -71,6 +71,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public abstract class MediaRoute2ProviderService extends Service {
private static final String TAG = "MR2ProviderService";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
/**
* The {@link Intent} action that must be declared as handled by the service.
@@ -238,6 +239,11 @@ public abstract class MediaRoute2ProviderService extends Service {
@NonNull RoutingSessionInfo sessionInfo) {
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+ if (DEBUG) {
+ Log.d(TAG, "notifySessionCreated: Creating a session. requestId=" + requestId
+ + ", sessionInfo=" + sessionInfo);
+ }
+
if (requestId != REQUEST_ID_NONE && !removeRequestId(requestId)) {
Log.w(TAG, "notifySessionCreated: The requestId doesn't exist. requestId=" + requestId);
return;
@@ -269,6 +275,10 @@ public abstract class MediaRoute2ProviderService extends Service {
public final void notifySessionUpdated(@NonNull RoutingSessionInfo sessionInfo) {
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+ if (DEBUG) {
+ Log.d(TAG, "notifySessionUpdated: Updating session id=" + sessionInfo);
+ }
+
String sessionId = sessionInfo.getId();
synchronized (mSessionLock) {
if (mSessionInfo.containsKey(sessionId)) {
@@ -299,6 +309,10 @@ public abstract class MediaRoute2ProviderService extends Service {
if (TextUtils.isEmpty(sessionId)) {
throw new IllegalArgumentException("sessionId must not be empty");
}
+ if (DEBUG) {
+ Log.d(TAG, "notifySessionReleased: Releasing session id=" + sessionId);
+ }
+
RoutingSessionInfo sessionInfo;
synchronized (mSessionLock) {
sessionInfo = mSessionInfo.remove(sessionId);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 0f538a57a5ee..6fe48a4ef7e0 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -378,6 +378,7 @@ public final class MediaRouter2 {
*/
public void transferTo(@NonNull MediaRoute2Info route) {
Objects.requireNonNull(route, "route must not be null");
+ Log.v(TAG, "Transferring to route: " + route);
transfer(getCurrentController(), route);
}
@@ -620,6 +621,7 @@ public final class MediaRouter2 {
changedRoutes.add(route);
}
}
+ mShouldUpdateRoutes = true;
}
if (changedRoutes.size() > 0) {
notifyRoutesChanged(changedRoutes);
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 5a7c87e0235d..773263865135 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -321,6 +321,8 @@ public final class MediaRouter2Manager {
Objects.requireNonNull(packageName, "packageName must not be null");
Objects.requireNonNull(route, "route must not be null");
+ Log.v(TAG, "Selecting route. packageName= " + packageName + ", route=" + route);
+
List<RoutingSessionInfo> sessionInfos = getRoutingSessions(packageName);
RoutingSessionInfo targetSession = sessionInfos.get(sessionInfos.size() - 1);
transfer(targetSession, route);
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index af63070027a2..57a04fd70a0b 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -29,6 +29,7 @@ import android.media.MediaCodec.LinearBlock;
@SystemApi
public class MediaEvent extends FilterEvent {
private long mNativeContext;
+ private boolean mReleased = false;
private final Object mLock = new Object();
private native Long nativeGetAudioHandle();
@@ -181,7 +182,21 @@ public class MediaEvent extends FilterEvent {
*/
@Override
protected void finalize() {
- nativeFinalize();
- mNativeContext = 0;
+ release();
+ }
+
+ /**
+ * Releases the MediaEvent object.
+ * @hide
+ */
+ public void release() {
+ synchronized (mLock) {
+ if (mReleased) {
+ return;
+ }
+ nativeFinalize();
+ mNativeContext = 0;
+ mReleased = true;
+ }
}
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 7e721406a300..e8f18a59049e 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -314,8 +314,9 @@ MediaEvent::~MediaEvent() {
if (mIonHandle != NULL) {
delete mIonHandle;
}
- if (mC2Buffer != NULL) {
- mC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this);
+ std::shared_ptr<C2Buffer> pC2Buffer = mC2Buffer.lock();
+ if (pC2Buffer != NULL) {
+ pC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this);
}
}
@@ -340,15 +341,17 @@ jobject MediaEvent::getLinearBlock() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
context->mBlock = block;
- mC2Buffer = context->toC2Buffer(0, mDataLength);
+ std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, mDataLength);
+ context->mBuffer = pC2Buffer;
+ mC2Buffer = pC2Buffer;
if (mAvHandle->numInts > 0) {
// use first int in the native_handle as the index
int index = mAvHandle->data[mAvHandle->numFds];
std::shared_ptr<C2Param> c2param = std::make_shared<C2DataIdInfo>(index, mDataId);
std::shared_ptr<C2Info> info(std::static_pointer_cast<C2Info>(c2param));
- mC2Buffer->setInfo(info);
+ pC2Buffer->setInfo(info);
}
- mC2Buffer->registerOnDestroyNotify(&DestroyCallback, this);
+ pC2Buffer->registerOnDestroyNotify(&DestroyCallback, this);
jobject linearBlock =
env->NewObject(
env->FindClass("android/media/MediaCodec$LinearBlock"),
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index c469a3ad8b76..83e9db796363 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -130,7 +130,7 @@ struct MediaEvent : public RefBase {
jweak mMediaEventObj;
jweak mLinearBlockObj;
C2HandleIon* mIonHandle;
- std::shared_ptr<C2Buffer> mC2Buffer;
+ std::weak_ptr<C2Buffer> mC2Buffer;
};
struct Filter : public RefBase {
diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types
index 05a2e92ca080..f3730f2756d2 100644
--- a/mime/java-res/android.mime.types
+++ b/mime/java-res/android.mime.types
@@ -84,6 +84,7 @@
?audio/sp-midi smf
?audio/x-matroska mka
?audio/x-pn-realaudio ra
+?audio/x-mpeg mp3
?image/bmp bmp
?image/heic heic
diff --git a/packages/CarSystemUI/res/xml/overlayable.xml b/packages/CarSystemUI/res/xml/overlayable.xml
deleted file mode 100644
index 2b6e66e28b5f..000000000000
--- a/packages/CarSystemUI/res/xml/overlayable.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <overlayable name="SystemBarsLayouts">
- <policy type="product|signature">
- <item type="layout" name="car_navigation_bar" />
- </policy>
- </overlayable>
-</resources> \ No newline at end of file
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index 98687b40af16..a346cb2c1b2d 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4469836075319831821">"Gest. cues impr."</string>
+ <string name="app_label" msgid="4469836075319831821">"Gestor de cues d\'impressió"</string>
<string name="more_options_button" msgid="2243228396432556771">"Més opcions"</string>
<string name="label_destination" msgid="9132510997381599275">"Destinació"</string>
<string name="label_copies" msgid="3634531042822968308">"Còpies"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 0def17e1c21a..cc3b2aa33695 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -90,7 +90,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"Use for contact sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
- <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Access"</string>
+ <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 0def17e1c21a..cc3b2aa33695 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -90,7 +90,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"Use for contact sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
- <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Access"</string>
+ <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 0def17e1c21a..cc3b2aa33695 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -90,7 +90,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"Use for contact sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
- <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Access"</string>
+ <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 0def17e1c21a..cc3b2aa33695 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -90,7 +90,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"Use for contact sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
- <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Access"</string>
+ <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
<string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 1ee06b8353c9..279aca0731f7 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -545,7 +545,7 @@
<string name="profile_info_settings_title" msgid="105699672534365099">"Профильдік ақпарат"</string>
<string name="user_need_lock_message" msgid="4311424336209509301">"Шектелген профайл жасақтауға дейін қолданбалар мен жеке деректерді қорғау үшін экран бекітпесін тағайындау қажет."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Бекітпе тағайындау"</string>
- <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> атты пайдаланушыға ауысу"</string>
+ <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> пайдаланушысына ауысу"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Қонақты енгізу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Қонақты өшіру"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Қонақ"</string>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 4e17062fc52c..b64a9e7a25bf 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -39,6 +39,8 @@
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <!-- ACCESS_BACKGROUND_LOCATION is needed for testing purposes only. -->
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
diff --git a/packages/SoundPicker/AndroidManifest.xml b/packages/SoundPicker/AndroidManifest.xml
index 9d0818230a02..73d99a55efdd 100644
--- a/packages/SoundPicker/AndroidManifest.xml
+++ b/packages/SoundPicker/AndroidManifest.xml
@@ -11,6 +11,7 @@
<application
android:allowBackup="false"
+ android:label="@string/app_label"
android:supportsRtl="true">
<receiver android:name="RingtoneReceiver">
<intent-filter>
diff --git a/packages/SoundPicker/res/values/strings.xml b/packages/SoundPicker/res/values/strings.xml
index 56ed5fd5d58e..04a2c2bb83c3 100644
--- a/packages/SoundPicker/res/values/strings.xml
+++ b/packages/SoundPicker/res/values/strings.xml
@@ -37,4 +37,7 @@
<string name="unable_to_add_ringtone">Unable to add custom ringtone</string>
<!-- Text for the Toast displayed when deleting a custom ringtone fails. -->
<string name="unable_to_delete_ringtone">Unable to delete custom ringtone</string>
+
+ <!-- Text for the name of the app. [CHAR LIMIT=12] -->
+ <string name="app_label">Sounds</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-mn/strings.xml b/packages/SystemUI/res-product/values-mn/strings.xml
index 6a0f668986f8..0b47eb06da30 100644
--- a/packages/SystemUI/res-product/values-mn/strings.xml
+++ b/packages/SystemUI/res-product/values-mn/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Илүү хурдан цэнэглэхийн тулд утсыг дахин байрлуулна уу"</string>
<string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Утасгүйгээр цэнэглэхийн тулд утсыг дахин байрлуулна уу"</string>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TВ төхөөрөмж удахгүй унтрах тул асаалттай хэвээр байлгахын тулд товчлуурыг дарна уу."</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV төхөөрөмж удахгүй унтрах тул асаалттай хэвээр байлгахын тулд товчлуурыг дарна уу."</string>
<string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Төхөөрөмж удахгүй унтрах тул асаалттай хэвээр байлгахын тулд дарна уу."</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Таблетад SIM карт алга байна."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Утсанд SIM карт алга байна."</string>
diff --git a/packages/SystemUI/res/drawable/bubble_stack_user_education_bg_rtl.xml b/packages/SystemUI/res/drawable/bubble_stack_user_education_bg_rtl.xml
new file mode 100644
index 000000000000..c7baba14b5e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/bubble_stack_user_education_bg_rtl.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="?android:attr/colorAccent"/>
+ <corners
+ android:bottomLeftRadius="360dp"
+ android:topLeftRadius="360dp" />
+</shape>
diff --git a/packages/SystemUI/res/layout/bubble_stack_user_education.xml b/packages/SystemUI/res/layout/bubble_stack_user_education.xml
index 81b28e612993..616403219bc6 100644
--- a/packages/SystemUI/res/layout/bubble_stack_user_education.xml
+++ b/packages/SystemUI/res/layout/bubble_stack_user_education.xml
@@ -33,7 +33,8 @@
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
- android:maxLines="1"
+ android:maxLines="2"
+ android:ellipsize="end"
android:text="@string/bubbles_user_education_title"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"/>
@@ -41,6 +42,7 @@
android:id="@+id/user_education_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:ellipsize="end"
android:text="@string/bubbles_user_education_description"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"/>
diff --git a/packages/SystemUI/res/layout/bubbles_manage_button_education.xml b/packages/SystemUI/res/layout/bubbles_manage_button_education.xml
index 7313d54c599a..87dd58e4f0ed 100644
--- a/packages/SystemUI/res/layout/bubbles_manage_button_education.xml
+++ b/packages/SystemUI/res/layout/bubbles_manage_button_education.xml
@@ -31,7 +31,6 @@
android:layout_marginEnd="24dp"
android:orientation="vertical"
android:background="@drawable/bubble_stack_user_education_bg"
- android:alpha="0.9"
>
<TextView
@@ -41,7 +40,8 @@
android:paddingStart="16dp"
android:paddingBottom="16dp"
android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
- android:maxLines="1"
+ android:maxLines="2"
+ android:ellipsize="end"
android:text="@string/bubbles_user_education_manage_title"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"/>
@@ -52,12 +52,15 @@
android:paddingStart="16dp"
android:paddingBottom="24dp"
android:text="@string/bubbles_user_education_manage"
+ android:maxLines="2"
+ android:ellipsize="end"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"/>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+ android:id="@+id/button_layout"
android:orientation="horizontal" >
<com.android.systemui.statusbar.AlphaOptimizedButton
@@ -70,7 +73,6 @@
android:clickable="false"
android:text="@string/manage_bubbles_text"
android:textColor="?attr/wallpaperTextColor"
- android:alpha="0.89"
/>
<com.android.systemui.statusbar.AlphaOptimizedButton
@@ -85,4 +87,4 @@
/>
</LinearLayout>
</LinearLayout>
-</com.android.systemui.bubbles.BubbleManageEducationView> \ No newline at end of file
+</com.android.systemui.bubbles.BubbleManageEducationView>
diff --git a/packages/SystemUI/res/layout/global_actions_power_dialog.xml b/packages/SystemUI/res/layout/global_actions_power_dialog.xml
new file mode 100644
index 000000000000..ff3f0fb74cd5
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_power_dialog.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:divider="@drawable/controls_list_divider"
+ android:showDividers="middle"
+/>
+
diff --git a/packages/SystemUI/res/layout/global_actions_power_item.xml b/packages/SystemUI/res/layout/global_actions_power_item.xml
new file mode 100644
index 000000000000..0d060b63486f
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_power_item.xml
@@ -0,0 +1,45 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<com.android.systemui.globalactions.GlobalActionsItem
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/global_actions_power_dialog_item_width"
+ android:layout_height="@dimen/global_actions_power_dialog_item_height"
+ android:gravity="bottom|center_horizontal"
+ android:orientation="vertical"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
+ android:stateListAnimator="@anim/control_state_list_animator">
+ <ImageView
+ android:id="@*android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginBottom="45dp"
+ android:scaleType="centerInside"
+ android:tint="@color/control_primary_text" />
+ <TextView
+ android:id="@*android:id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:ellipsize="marquee"
+ android:layout_marginBottom="16dp"
+ android:maxLines="1"
+ android:textSize="16sp"
+ android:gravity="center"
+ android:textColor="@color/control_primary_text"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+</com.android.systemui.globalactions.GlobalActionsItem>
+
diff --git a/packages/SystemUI/res/layout/home_handle.xml b/packages/SystemUI/res/layout/home_handle.xml
index 7c5db105a09e..54a0b9fba39c 100644
--- a/packages/SystemUI/res/layout/home_handle.xml
+++ b/packages/SystemUI/res/layout/home_handle.xml
@@ -21,6 +21,7 @@
android:layout_width="@dimen/navigation_home_handle_width"
android:layout_height="match_parent"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_home"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 48b25b0773e4..1443d18c2b9b 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1013,10 +1013,10 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Stelselnavigasie is opgedateer. Gaan na Instellings toe om veranderinge te maak."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gaan na Instellings toe om stelselnavigasie op te dateer"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Bystandmodus"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"Gesprek is op prioriteit gestel"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"Gesprek is as prioriteit gestel"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioriteitgesprekke sal:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Wys boaan gespreksafdeling"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Wys profielprent op slotskerm"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Boaan gespreksafdeling wys"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Profielprent op slotskerm wys"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Verskyn as \'n swewende borrel bo-oor programme"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Onderbreek Moenie Steur Nie"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Het dit"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hou en sleep om kontroles te herrangskik"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Alle kontroles is verwyder"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Veranderinge is nie gestoor nie"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Die lys met alle kontroles kon nie gelaai word nie."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kontroles kon nie gelaai word nie. Gaan die <xliff:g id="APP">%s</xliff:g>-program na om seker te maak dat die programinstellings nie verander het nie."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Versoenbare kontroles is nie beskikbaar nie"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Ander"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Voeg by toestelkontroles"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Voeg by"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 9a75c1c0879c..8fbad2cfc1a2 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"መቆጣጠሪያዎችን ዳግም ለማስተካከል ይያዙ እና ይጎትቱ"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"ሁሉም መቆጣጠሪያዎች ተወግደዋል"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ለውጦች አልተቀመጡም"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"የሁሉም መቆጣጠሪያዎች ዝርዝር ሊጫን አልተቻለም።"</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ሌላ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ወደ የመሣሪያ መቆጣጠሪያዎች ያክሉ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"አክል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index bfa21071d815..c4d86e74b361 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1069,7 +1069,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"اضغط مع الاستمرار واسحب لإعادة ترتيب عناصر التحكّم."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"تمت إزالة كل عناصر التحكّم."</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"لم يتم حفظ التغييرات."</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"تعذّر تحميل قائمة كل عناصر التحكّم."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"غير ذلك"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"إضافة إلى أدوات التحكم بالجهاز"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"إضافة"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index ca21ff674595..7bacd0d2f8d1 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"নিয়ন্ত্ৰণসমূহ পুনৰ সজাবলৈ ধৰি ৰাখক আৰু টানি আনি এৰক"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"সকলো নিয়ন্ত্ৰণ আঁতৰোৱা হৈছে"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"সালসলনিসমূহ ছেভ নহ’ল"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"নিয়ন্ত্ৰণসমূহৰ সম্পূর্ণ সূচীখন ল’ড কৰিব পৰা নগ’ল।"</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহত যোগ দিয়ক"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ দিয়ক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 3a7c98ca34cf..cb7ec9eccc82 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1002,8 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Yuxarıya sağa köçürün"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Aşağıya sola köçürün"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Aşağıya sağa köçürün"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Qabarcığı ləğv edin"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Söhbətdən gələn bildirişi göstərməyin"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Yumrucuğu ləğv edin"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Söhbəti yumrucuqda göstərmə"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Yumrucuqlardan istifadə edərək söhbət edin"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Yeni söhbətlər üzən nişanlar və ya yumrucuqlar kimi görünür. Yumrucuğu açmaq üçün toxunun. Hərəkət etdirmək üçün sürüşdürün."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Yumrucuqları istənilən vaxt idarə edin"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Nizamlayıcıları yenidən tənzimləmək üçün tutub sürüşdürün"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Bütün nizamlayıcılar silindi"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Dəyişikliklər yadda saxlanmadı"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Bütün nizamlayıcıların siyahısı yüklənmədi."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Digər"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Cihaz idarəetmələrinə əlavə edin"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Əlavə edin"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index cdface92a34c..5959e2600d19 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1007,7 +1007,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Premesti gore desno"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Premesti dole levo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Premesti dole desno"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Odbacivanje oblačića"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Odbaci oblačić"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne koristi oblačiće za konverzaciju"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Ćaskajte u oblačićima"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nove konverzacije se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da biste otvorili oblačić. Prevucite da biste ga premestili."</string>
@@ -1019,9 +1019,9 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Idite u Podešavanja da biste ažurirali navigaciju sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravnosti"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Konverzacija je podešena na prioritetnu"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioritetne konverzacije će:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuje se u vrhu odeljka za konverzacije"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazuje sliku profila na zaključanom ekranu"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioritetne konverzacije:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"se prikazuju u vrhu odeljka za konverzacije"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"prikazuju sliku profila na zaključanom ekranu"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Prikazuju se plutajući oblačići preko aplikacija"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ometa podešavanje Ne uznemiravaj"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Važi"</string>
@@ -1051,7 +1051,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Zadržite i prevucite da biste promenili raspored kontrola"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Sve kontrole su uklonjene"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Promene nisu sačuvane"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Učitavanje liste svih kontrola nije uspelo."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Učitavanje kontrola nije uspelo. Pogledajte aplikaciju <xliff:g id="APP">%s</xliff:g> da biste se uverili da se podešavanja aplikacije nisu promenila."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kompatibilne kontrole nisu dostupne"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodajte u kontrole uređaja"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 32ec1841ea3e..2c84b066bb11 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -419,7 +419,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ліміт <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Папярэджанне: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Працоўны профіль"</string>
- <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Начны рэжым"</string>
+ <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Начная падсветка"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Уключаць увечары"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Да ўсходу сонца"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Уключыць у <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -1024,7 +1024,7 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Перайдзіце ў Налады, каб абнавіць параметры навігацыі ў сістэме"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Рэжым чакання"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Размова пазначана як прыярытэтная"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Прыярытэтныя размовы будуць:"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Прыярытэтныя размовы:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Паказваюцца ўверсе раздзела размоў"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Паказваюць відарыс профілю на экране блакіроўкі"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Паказваюцца як рухомыя апавяшчэнні паверх праграм"</string>
@@ -1057,7 +1057,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Каб змяніць парадак элементаў кіравання, утрымлівайце і перацягвайце іх"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Усе элементы кіравання выдалены"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Змяненні не захаваны"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Не ўдалося загрузіць спіс усіх сродкаў кіравання."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Іншае"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Дадаць у элементы кіравання прыладай"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Дадаць"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a2a2671b3f70..06306a39ff5a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1002,7 +1002,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Преместване горе вдясно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Преместване долу вляво"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Преместване долу вдясно"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Балонче: Отхвърляне"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Отхвърляне на балончетата"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Без балончета за разговора"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Чат с балончета"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Новите разговори се показват като плаващи икони, или балончета. Докоснете балонче, за да го отворите, или го плъзнете, за да го преместите."</string>
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим на готовност"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Разговорът е зададен като приоритетен"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Приоритетните разговори ще:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Показване върху секцията с разговори"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Показване на снимката на потр. профил на закл. екран"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"се показват върху секцията с разговори;"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"показват снимката на потребителския профил на заключения екран."</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Показва се като плаващо балонче върху приложенията"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Прекъсване на режима „Не безпокойте“"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Разбрах"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Задръжте и плъзнете, за да пренаредите контролите"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Всички контроли са премахнати"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Промените не са запазени"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Списъкът с всички контроли не бе зареден."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друго"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Добавяне към контролите за устройството"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Добавяне"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 7a9fecad5f9d..33b733cf2b61 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -994,7 +994,7 @@
<string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> বাবলের জন্য সেটিংস"</string>
<string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ওভারফ্লো"</string>
<string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"স্ট্যাকে আবার যোগ করুন"</string>
- <string name="manage_bubbles_text" msgid="6856830436329494850">"ম্যানেজ করা"</string>
+ <string name="manage_bubbles_text" msgid="6856830436329494850">"ম্যানেজ করুন"</string>
<string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপ থেকে <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপ এবং আরও <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>টি থেকে <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_accessibility_action_move" msgid="3185080443743819178">"সরান"</string>
@@ -1007,7 +1007,7 @@
<string name="bubbles_user_education_title" msgid="5547017089271445797">"বাবল ব্যবহার করে চ্যাট করুন"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"নতুন কথোপকথন ভেসে থাকা আইকন বা বাবল হিসেবে দেখানো হয়। বাবল খুলতে ট্যাপ করুন। সেটি সরাতে ধরে টেনে আনুন।"</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"যেকোনও সময় বাবল নিয়ন্ত্রণ করুন"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"এই অ্যাপ থেকে বাবল বন্ধ করতে ম্যানেজ করুন বিকল্প ট্যাপ করুন"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"এই অ্যাপ থেকে বাবল বন্ধ করতে \'ম্যানেজ করুন\' বিকল্প ট্যাপ করুন"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"বুঝেছি"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> সেটিংস"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"সিস্টেম নেভিগেশন আপডেট হয়েছে। পরিবর্তন করার জন্য সেটিংসে যান।"</string>
@@ -1015,7 +1015,7 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"স্ট্যান্ডবাই"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"কথোপকথনকে \'গুরুত্বপূর্ণ\' হিসেবে সেট করা হয়েছে"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"গুরুত্বপূর্ণ কথোপকথন:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"কথোপকথনের বিভাগের উপরে দেখান"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"কথোপকথন বিভাগের একদম উপরে দেখুন"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"লক স্ক্রিনে প্রোফাইল ছবি দেখান"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"অ্যাপের উপরে একটি ভাসমান বুদবুদ হিসেবে দেখা যাবে"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"বিরক্ত করবে না মোডে ব্যাঘাত ঘটাতে পারে"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"কন্ট্রোলগুলিকে আবার সাজানোর জন্য ধরে রেখে টেনে আনুন"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"সমস্ত কন্ট্রোল সরানো হয়েছে"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"পরিবর্তন সেভ করা হয়নি"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"সব কন্ট্রোলের তালিকা লোড করা যায়নি।"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"কন্ট্রোল লোড করা যায়নি। অ্যাপ সেটিংসে কোনও পরিবর্তন করা হয়েছে কিনা তা ভাল করে দেখে নিতে <xliff:g id="APP">%s</xliff:g> অ্যাপ চেক করুন।"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"মানানসই কন্ট্রোল উপলভ্য নেই"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইস কন্ট্রোলে যোগ করুন"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ করুন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 49fae626fa5a..930f50b74f1a 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -57,12 +57,12 @@
<string name="label_view" msgid="6815442985276363364">"Prikaži"</string>
<string name="always_use_device" msgid="210535878779644679">"Uvijek otvori aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> kada se poveže <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
<string name="always_use_accessory" msgid="1977225429341838444">"Uvijek otvori aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> kada se poveže <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
- <string name="usb_debugging_title" msgid="8274884945238642726">"Omogućiti otklanjanje grešaka putem uređaja spojenog na USB?"</string>
+ <string name="usb_debugging_title" msgid="8274884945238642726">"Omogućiti otklanjanje grešaka putem USB-a?"</string>
<string name="usb_debugging_message" msgid="5794616114463921773">"RSA otisak prsta za otključavanje računara je: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
<string name="usb_debugging_always" msgid="4003121804294739548">"Uvijek dozvoli sa ovog računara"</string>
<string name="usb_debugging_allow" msgid="1722643858015321328">"Dozvoli"</string>
- <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Otklanjanje grešaka putem uređaja spojenog na USB nije dozvoljeno"</string>
- <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Korisnik koji je trenutno prijavljen na ovaj uređaj ne može uključiti opciju za otklanjanje grešaka koristeći USB. Da koristite tu funkciju, prebacite se na primarnog korisnika."</string>
+ <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Otklanjanje grešaka putem USB-a nije dozvoljeno"</string>
+ <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Korisnik koji je trenutno prijavljen na ovaj uređaj ne može uključiti opciju za otklanjanje grešaka putem USB-a. Da koristite tu funkciju, prebacite se na primarnog korisnika."</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Dozvoliti bežično otklanjanje grešaka na ovoj mreži?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Naziv mreže (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa WiFi mreže (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Uvijek dozvoli na ovoj mreži"</string>
@@ -1013,7 +1013,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nemoj prikazivati razgovor u oblačićima"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatajte koristeći oblačiće"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Novi razgovori se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da otvorite oblačić. Prevucite da ga premjestite."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Upravljajte oblačićima u svakom momentu"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Upravljajte oblačićima u svakom trenutku"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Dodirnite Upravljaj da isključite oblačiće iz ove aplikacije"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Razumijem"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Postavke aplikacije <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1022,8 +1022,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Razgovor je postavljen kao prioritetan"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioritetni razgovori će:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuje se na vrhu odjeljka za razgovor"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazuje sliku profila na zaključanom ekranu"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Biti prikazani na vrhu odjeljka za razgovor"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazivati sliku profila na zaključanom ekranu"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Izgleda kao plutajući oblačić iznad aplikacija"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Prekida način rada Ne ometaj"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Razumijem"</string>
@@ -1053,7 +1053,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Držite i prevucite da preuredite kontrole"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Sve kontrole su uklonjene"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Promjene nisu sačuvane"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Učitavanje liste svih kontrola nije uspjelo."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Učitavanje kontrola nije uspjelo. Provjerite aplikaciju <xliff:g id="APP">%s</xliff:g> da se uvjerite da postavke aplikacije nisu izmijenjene."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kompatibilne kontrole su nedostupne"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodajte u kontrole uređaja"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
@@ -1075,7 +1076,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"Greška, ponovni pokušaj…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"Pristup uređaju <xliff:g id="DEVICE">%1$s</xliff:g> nije uspio. Provjerite aplikaciju <xliff:g id="APPLICATION">%2$s</xliff:g> da se uvjerite da je kontrola i dalje dostupna i da se postavke aplikacije nisu promijenile."</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Pristupanje uređaju <xliff:g id="DEVICE">%1$s</xliff:g> nije uspjelo. Provjerite aplikaciju <xliff:g id="APPLICATION">%2$s</xliff:g> da se uvjerite da je kontrola i dalje dostupna i da se postavke aplikacije nisu promijenile."</string>
<string name="controls_open_app" msgid="483650971094300141">"Otvori aplikaciju"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Nije moguće učitati status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Greška, pokušajte ponovo"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5cc0853a6e18..53e2b867cfe6 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"La conversa s\'ha definit com a prioritària"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Les converses prioritàries:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Mostra a la part superior de la secció de converses"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostra la foto de perfil a la pantalla de bloqueig"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Es mostraran a la part superior de la secció de converses"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostraran la foto de perfil a la pantalla de bloqueig"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Es mostra com a bombolla flotant en primer pla"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interromp el mode No molestis"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Entesos"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantén premut i arrossega per reorganitzar els controls"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"S\'han suprimit tots els controls"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Els canvis no s\'han desat"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"No s\'ha pogut carregar la llista completa de controls."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altres"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Afegeix als controls de dispositius"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Afegeix"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a071793af881..51ed8c36080a 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1019,7 +1019,7 @@
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Nastavení bublin můžete kdykoli upravit"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Bubliny pro tuto aplikaci můžete vypnout klepnutím na Spravovat"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Rozumím"</string>
- <string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – nastavení"</string>
+ <string name="bubbles_app_settings" msgid="5779443644062348657">"Nastavení <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systémová navigace byla aktualizována. Chcete-li provést změny, přejděte do Nastavení."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Přejděte do Nastavení a aktualizujte systémovou navigaci"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostní režim"</string>
@@ -1057,7 +1057,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Ovládací prvky můžete uspořádat podržením a přetažením"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Všechny ovládací prvky byly odstraněny"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Změny nebyly uloženy"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Načtení seznamu všech ovládacích prvků se nezdařilo."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Jiné"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Přidání ovládání zařízení"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Přidat"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f1bbbff3d7b6..da3bbaa4b957 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1002,7 +1002,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Flyt op til højre"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Flyt ned til venstre"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Flyt ned til højre"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Afvis bobbel"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Afvis boble"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Vis ikke samtaler i bobler"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat ved hjælp af bobler"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nye samtaler vises som svævende ikoner eller bobler. Tryk for at åbne boblen. Træk for at flytte den."</string>
@@ -1013,10 +1013,10 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigationen blev opdateret. Gå til Indstillinger for at foretage ændringer."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gå til Indstillinger for at opdatere systemnavigationen"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"Samtalen er angivet som prioritet"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"Samtalen er angivet som prioriteret"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Følgende gælder for prioriterede samtaler:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Vis i toppen af samtalesektionen"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Vis profilbillede på låseskærm"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Vises øverst i samtalesektionen"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Viser profilbillede på låseskærm"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Vis som en boble oven på apps"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Afbryd Forstyr ikke"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1041,11 +1041,12 @@
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"fjern fra favoritter"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"Flyt til position <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"Betjeningselementer"</string>
- <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Vælg, hvilke indstillinger der skal være i menuen for afbryderknappen"</string>
+ <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Vælg de indstillinger, der skal vises i menuen for afbryderknappen"</string>
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Flyt rundt på styringselementer ved at holde dem nede og trække"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Alle styringselementerne blev fjernet"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Ændringerne blev ikke gemt"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Listen over styringselementer kunne ikke indlæses."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Betjeningselementerne kunne ikke indlæses. Tjek <xliff:g id="APP">%s</xliff:g>-appen for at sørge for, at dine appindstillinger ikke er blevet ændret."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kompatible betjeningselementer er ikke tilgængelige"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Andre"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Føj til enhedsstyring"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Tilføj"</string>
@@ -1067,7 +1068,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"Fejl. Prøver igen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Styringselement ikke tilgængeligt"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"Der kunne ikke skaffes adgang til <xliff:g id="DEVICE">%1$s</xliff:g>. Tjek <xliff:g id="APPLICATION">%2$s</xliff:g>-appen for at sikre at styringselementet stadig er tilgængeligt, og at appens indstillinger ikke er blevet ændret."</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Der kunne ikke skaffes adgang til <xliff:g id="DEVICE">%1$s</xliff:g>. Tjek <xliff:g id="APPLICATION">%2$s</xliff:g>-appen for at sikre, at styringselementet stadig er tilgængeligt, og at appens indstillinger ikke er blevet ændret."</string>
<string name="controls_open_app" msgid="483650971094300141">"Åbn app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Statussen kan ikke indlæses"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Der opstod en fejl. Prøv igen"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3397cd615138..5a44c238e46c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -510,8 +510,7 @@
<string name="clear_all_notifications_text" msgid="348312370303046130">"Alle löschen"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Verwalten"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Verlauf"</string>
- <!-- no translation found for notification_section_header_incoming (850925217908095197) -->
- <skip />
+ <string name="notification_section_header_incoming" msgid="850925217908095197">"Neu"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"Lautlos"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"Benachrichtigungen"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"Unterhaltungen"</string>
@@ -1046,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Zum Verschieben von Steuerelementen halten und ziehen"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Alle Steuerelemente entfernt"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Änderungen nicht gespeichert"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Fehler beim Laden der Liste mit Steuerelementen."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Steuerelemente konnten nicht geladen werden. Prüfe in der <xliff:g id="APP">%s</xliff:g> App, ob die Einstellungen möglicherweise geändert wurden."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kompatible Steuerelemente nicht verfügbar"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Andere"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Zur Gerätesteuerung hinzufügen"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Hinzufügen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f24f7457b0c6..313eaaadd48a 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1014,7 +1014,7 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Μεταβείτε στις Ρυθμίσεις για να ενημερώσετε την πλοήγηση συστήματος"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Κατάσταση αναμονής"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Ορίστηκε ως συζήτηση προτεραιότητας"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Οι συζητήσεις προτεραιότητας θα:"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Οι συζητήσεις προτεραιότητας θα έχουν τα εξής χαρακτηριστικά:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Εμφάνιση στο επάνω μέρος της ενότητας συνομιλιών"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Εμφάνιση εικόνας προφίλ στην οθόνη κλειδώματος"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Κινούμενο συννεφάκι στο επάνω μέρος των εφαρμογών"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Κρατήστε και σύρετε για αναδιάταξη των στοιχείων ελέγχου"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Όλα τα στοιχεία ελέγχου καταργήθηκαν"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Οι αλλαγές δεν αποθηκεύτηκαν"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Ανεπιτυχής φόρτωση λίστας όλων των στοιχ. ελέγχου."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Άλλο"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Προσθήκη στα στοιχεία ελέγχου συσκευής"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Προσθήκη"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ac20c8477d47..a94d8d383275 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"All controls removed"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Changes not saved"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"The list of all controls could not be loaded."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Controls could not be loaded. Check the <xliff:g id="APP">%s</xliff:g> app to make sure that the app settings haven’t changed."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Compatible controls unavailable"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 233664e5fbc7..3dcf7fcedb46 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"All controls removed"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Changes not saved"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"The list of all controls could not be loaded."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Controls could not be loaded. Check the <xliff:g id="APP">%s</xliff:g> app to make sure that the app settings haven’t changed."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Compatible controls unavailable"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ac20c8477d47..a94d8d383275 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"All controls removed"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Changes not saved"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"The list of all controls could not be loaded."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Controls could not be loaded. Check the <xliff:g id="APP">%s</xliff:g> app to make sure that the app settings haven’t changed."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Compatible controls unavailable"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ac20c8477d47..a94d8d383275 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"All controls removed"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Changes not saved"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"The list of all controls could not be loaded."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Controls could not be loaded. Check the <xliff:g id="APP">%s</xliff:g> app to make sure that the app settings haven’t changed."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Compatible controls unavailable"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index f37742d62062..a8c0aa125802 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎Hold &amp; drag to rearrange controls‎‏‎‎‏‎"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎All controls removed‎‏‎‎‏‎"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎Changes not saved‎‏‎‎‏‎"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‎‎‎The list of all controls could not be loaded.‎‏‎‎‏‎"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎Controls could not be loaded. Check the ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎ app to make sure that the app settings haven’t changed.‎‏‎‎‏‎"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎Compatible controls unavailable‎‏‎‎‏‎"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎Other‎‏‎‎‏‎"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎Add to device controls‎‏‎‎‏‎"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎Add‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index b4bba8f3145b..f09b0fce7a01 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1006,7 +1006,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No mostrar la conversación en burbujas"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat con burbujas"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Las conversaciones nuevas aparecen como elementos flotantes o burbujas. Presiona para abrir la burbuja. Arrástrala para moverla."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controla las burbujas en todo momento"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controla las burbujas"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Presiona Administrar para desactivar las burbujas de esta app"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Entendido"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Se estableció la conversación como prioritaria"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Las conversaciones prioritarias harán lo siguiente:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Se muestran en la parte superior de conversaciones"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Muestran una foto de perfil en pantalla de bloqueo"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Mostrarse en la parte superior de conversaciones"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrar una foto de perfil en pantalla de bloqueo"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecen como burbujas flotantes encima de apps"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Suspender No interrumpir"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Entendido"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantén presionado y arrastra un control para reubicarlo"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Se quitaron todos los controles"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"No se guardaron los cambios"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"No se cargó la lista completa de controles."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Otros"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Agregar a controles de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Agregar"</string>
@@ -1066,7 +1069,7 @@
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hubo un error. Reintentando…"</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>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"El control no está disponible"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"No se pudo acceder a <xliff:g id="DEVICE">%1$s</xliff:g>. Revisa la app de <xliff:g id="APPLICATION">%2$s</xliff:g> para asegurarte de que el control siga estando disponible y de que no haya cambiado la configuración de la app."</string>
<string name="controls_open_app" msgid="483650971094300141">"Abrir app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"No se pudo cargar el estado"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 6ffed58c3df8..889b7d071c37 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1003,10 +1003,10 @@
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mover abajo a la izquierda."</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mover abajo a la derecha"</string>
<string name="bubble_dismiss_text" msgid="1314082410868930066">"Cerrar burbuja"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No mostrar conversación en burbujas"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No mostrar conversación en burbuja"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatea con burbujas"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Las conversaciones nuevas aparecen como iconos flotantes llamadas \"burbujas\". Toca para abrir la burbuja. Arrastra para moverla."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controla las burbujas en cualquier momento"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controla las burbujas"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Toca Gestionar para desactivar las burbujas de esta aplicación"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Entendido"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Ajustes de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantén pulsado y arrastra un control para reubicarlo"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Todos los controles quitados"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"No se han guardado los cambios"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"No se ha podido cargar la lista de los controles."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Otros"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Añadir a control de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Añadir"</string>
@@ -1066,11 +1069,11 @@
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error; reintentando…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se ha encontrado"</string>
- <string name="controls_error_removed_title" msgid="1207794911208047818">"El control no está disponible"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"No se ha podido acceder a <xliff:g id="DEVICE">%1$s</xliff:g>. Comprueba que el control siga disponible en la aplicación <xliff:g id="APPLICATION">%2$s</xliff:g> y que no se haya modificado su configuración."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Control no disponible"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"No se ha podido acceder a <xliff:g id="DEVICE">%1$s</xliff:g>. Comprueba que el control siga disponible en la aplicación <xliff:g id="APPLICATION">%2$s</xliff:g> y que no se haya cambiado su configuración."</string>
<string name="controls_open_app" msgid="483650971094300141">"Abrir aplicación"</string>
<string name="controls_error_generic" msgid="352500456918362905">"No se ha podido cargar el estado"</string>
- <string name="controls_error_failed" msgid="960228639198558525">"Se ha producido un error. Vuelve a intentarlo."</string>
+ <string name="controls_error_failed" msgid="960228639198558525">"Error: Vuelve a intentarlo"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"En curso"</string>
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantén pulsado el botón de encendido para ver los controles nuevos"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Añadir controles"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 258bf5a581d0..0b3fc9d72bc6 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1007,7 +1007,7 @@
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Vestelge mullide abil"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Uued vestlused kuvatakse hõljuvate ikoonidena ehk mullidena. Puudutage mulli avamiseks. Lohistage mulli, et seda liigutada."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Juhtige mulle igal ajal"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Selle rakenduse puhul mullide väljalülitamiseks puudutage valikut Haldamine"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Selle rakenduse puhul mullide väljalülitamiseks puudutage valikut Halda"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Selge"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Rakenduse <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> seaded"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Süsteemis navigeerimine on värskendatud. Muutmiseks avage jaotis Seaded."</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Juhtelementide ümberpaigutamiseks hoidke neid all ja lohistage"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Kõik juhtelemendid eemaldati"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Muudatusi ei salvestatud"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Kõikide juhtelementide loendit ei saanud laadida."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Juhtelemente ei õnnestunud laadida. Kontrollige rakendust <xliff:g id="APP">%s</xliff:g> ja veenduge, et rakenduse seaded poleks muutunud."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Ühilduvaid juhtelemente pole saadaval"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Muu"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Seadmete juhtimisvidinate hulka lisamine"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Lisa"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index cb6f7967d3e8..e30552bbc776 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Egonean"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Lehentasunezko gisa ezarritako elkarrizketa"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Hau gertatuko da lehentasunezko elkarrizketekin:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Erakutsi elkarrizketen atalaren goialdean"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Erakutsi profileko argazkia pantaila blokeatuan"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Elkarrizketen atalaren goialdean erakutsiko dira."</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Profileko argazkia pantaila blokeatuan erakutsiko da."</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Burbuila gainerakor gisa agertuko da aplikazioen gainean"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Eten ez molestatzeko modua"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Ados"</string>
@@ -1025,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Gailuak kontrolatzeko widgetak"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"Gehitu kontrolatzeko aukerak konektatutako gailuetan"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"Gehitu konektatutako gailuak kontrolatzeko widgetak"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfiguratu gailuak kontrolatzeko widgetak"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Kontrol-aukerak atzitzeko, eduki sakatuta etengailua"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Aukeratu aplikazio bat kontrolatzeko aukerak gehitzeko"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Kontrolatzeko aukerak antolatzeko, eduki itzazu sakatuta, eta arrastatu"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Kendu dira kontrolatzeko aukera guztiak"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Ez dira gorde aldaketak"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Ezin izan da kargatu kontrol guztien zerrenda."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Beste bat"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Gehitu gailuak kontrolatzeko widgetetan"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Gehitu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index ae98244cf415..985b94354bc7 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"برای تغییر دادن ترتیب کنترل‌ها، آن‌ها را نگه دارید و بکشید"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"همه کنترل‌ها برداشته شده‌اند"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"تغییرات ذخیره نشد"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"فهرست همه کنترل‌ها را نمی‌توان بارگیری کرد."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"موارد دیگر"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"افزودن به کنترل‌های دستگاه"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"افزودن"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 05a88f4cc6ee..26bb615085cb 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1007,7 +1007,7 @@
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chattaile kuplien avulla"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Uudet keskustelut näkyvät kelluvina kuvakkeina tai kuplina. Avaa kupla napauttamalla. Siirrä sitä vetämällä."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Muuta kuplien asetuksia milloin tahansa"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Valitse Hallinnoi, jos haluat poistaa kuplat käytöstä tästä sovelluksesta"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Valitse Ylläpidä, jos haluat poistaa kuplat käytöstä tästä sovelluksesta"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Selvä"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: asetukset"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Järjestelmän navigointitapa vaihdettu. Voit muuttaa sitä asetuksista."</string>
@@ -1025,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"Suurennusikkuna"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurennusikkunan ohjaimet"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Laitteiden hallinta"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"Lisää säätimiä yhdistettyihin laitteisiisi"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"Lisää ohjaimia yhdistettyjä laitteita varten"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Laitteiden hallinnan käyttöönotto"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Voit käyttää säätimiä painamalla virtapainiketta"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Valitse sovellus lisätäksesi säätimiä"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Järjestele säätimiä koskettamalla pitkään ja vetämällä"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Kaikki säätimet poistettu"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Muutoksia ei tallennettu"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Kaikkien säätimien luetteloa ei voitu ladata."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Säätimiä ei voitu ladata. Avaa <xliff:g id="APP">%s</xliff:g> ja tarkista, että sovelluksen asetukset eivät ole muuttuneet."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Yhteensopivat säätimet eivät käytettävissä"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Muu"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Lisää laitteiden hallintaan"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Lisää"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index e7ef0824539f..185a972354bc 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1006,7 +1006,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne pas afficher les conversations dans des bulles"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Clavarder en utilisant des bulles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes (de bulles). Touchez une bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Gérer les paramètres des bulles"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Paramètres des bulles"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Toucher Gérer pour désactiver les bulles de cette application"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Paramètres <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1014,9 +1014,9 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accédez au menu Paramètres pour mettre à jour la navigation système"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"La conversation a été définie comme prioritaire"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Les conversations prioritaires :"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Afficher dans le haut de la section des conversations"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Afficher la photo de profil sur l\'écran verrouillé"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Pour les conversations prioritaires :"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"afficher dans le haut de la section des conversations"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"afficher la photo de profil sur l\'écran verrouillé"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Sous forme de bulle flottante, par-dessus les applis"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrompre le mode Ne pas déranger"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Maintenez le doigt sur l\'écran, puis glissez-le pour réorganiser les commandes"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Toutes les commandes ont été supprimées"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Modifications non enregistrées"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Impossible de charger la liste des commandes."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Autre"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes des appareils"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c7d88720a9df..d66621c7a7db 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1003,7 +1003,7 @@
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Déplacer en bas à gauche"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Déplacer en bas à droite"</string>
<string name="bubble_dismiss_text" msgid="1314082410868930066">"Fermer la bulle"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne pas afficher la conversations dans des bulles"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne pas afficher la conversation dans une bulle"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatter en utilisant des bulles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes ou bulles. Appuyez sur la bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Contrôler les paramètres des bulles"</string>
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Mode Veille imminent"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Conversation définie comme prioritaire"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Les conversations prioritaires :"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"En haut de la liste des conversations"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Photo de profil sur l\'écran de verrouillage"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"S\'affichent en haut de la liste des conversations"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Affichent la photo de profil sur l\'écran de verrouillage"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Sous forme d\'info-bulle au-dessus des applications"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrompre Ne pas déranger"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Appuyez et faites glisser pour réorganiser les commandes"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Toutes les commandes ont été supprimées"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Les modifications n\'ont pas été enregistrées"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Impossible de charger toutes les commandes."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Impossible de charger les commandes. Vérifiez l\'application <xliff:g id="APP">%s</xliff:g> pour vous assurer que les paramètres de l\'application n\'ont pas changé."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Commandes compatibles indisponibles"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Autre"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes de contrôle des appareils"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 93524f8492d8..426b413d2573 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1006,7 +1006,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Non mostrar a conversa como burbulla"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatear usando burbullas"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"As conversas novas aparecen como iconas flotantes ou burbullas. Toca para abrir a burbulla e arrastra para movela."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controlar as burbullas en calquera momento"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controla as burbullas"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Para desactivar as burbullas nesta aplicación, toca Xestionar"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Entendido"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"A conversa definiuse como prioritaria"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"As conversas prioritarias farán o seguinte:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Mostrar na parte superior da sección de conversas"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrar imaxe do perfil na pantalla de bloqueo"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Mostraranse na parte superior da sección de conversas"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrarán a imaxe do perfil na pantalla de bloqueo"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Mostrar como burbulla flotante sobre outras apps"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interromper modo Non molestar"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Entendido"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Para reorganizar os controis, mantenos premidos e arrástraos"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Quitáronse todos os controis"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Non se gardaron os cambios"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Non se puido cargar a lista de todos os controis."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outra"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Engadir ao control de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Engadir"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 473f6de00c89..c7f4ff2e1666 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"નિયંત્રણોને ફરીથી ગોઠવવા માટે તેમને હોલ્ડ કરીને ખેંચો"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"બધા નિયંત્રણો કાઢી નાખ્યા"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ફેરફારો સાચવ્યા નથી"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"બધા નિયંત્રણોની સૂચિ લોડ કરી શકાઈ નથી."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"નિયંત્રણો લોડ કરી શકાયા નથી. ઍપના સેટિંગ બદલાયા નથી તેની ખાતરી કરવા માટે <xliff:g id="APP">%s</xliff:g> ઍપ ચેક કરો."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"સુસંગત નિયંત્રણો ઉપલબ્ધ નથી"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"અન્ય"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ડિવાઇસનાં નિયંત્રણોમાં ઉમેરો"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ઉમેરો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 00389073626b..47d29d461bc6 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1015,7 +1015,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"सिस्टम नेविगेशन अपडेट हो गया. बदलाव करने के लिए \'सेटिंग\' पर जाएं."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"सिस्टम नेविगेशन अपडेट करने के लिए \'सेटिंग\' में जाएं"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्टैंडबाई"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"बातचीत को अहम बातचीत के तौर पर सेट किया गया है"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"बातचीत को \'अहम बातचीत\' के तौर पर सेट किया गया है"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"अहम बातचीत यहां दिखेगी:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"बातचीत सेक्शन में सबसे ऊपर दिखाएं"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो दिखाएं"</string>
@@ -1047,7 +1047,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"कंट्रोल का क्रम फिर से बदलने के लिए उन्हें दबाकर रखें और खींचें"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"सभी कंट्रोल हटा दिए गए"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"बदलाव सेव नहीं किए गए"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"सभी कंट्रोल की सूची लोड नहीं हो सकी."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"डिवाइस कंट्रोल में जोड़ें"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"जोड़ें"</string>
@@ -1067,7 +1070,7 @@
<string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"कोई गड़बड़ी हुई, फिर से कोशिश की जा रही है…"</string>
- <string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल मौजूद नहीं है"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल नहीं है"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"कंट्रोल मौजूद नहीं है"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> को ऐक्सेस नहीं किया जा सका. <xliff:g id="APPLICATION">%2$s</xliff:g> ऐप्लिकेशन देखें, ताकि यह पक्का किया जा सके कि कंट्रोल अब भी मौजूद है और सेटिंग में कोई बदलाव नहीं हुआ है."</string>
<string name="controls_open_app" msgid="483650971094300141">"ऐप्लिकेशन खोलें"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index b0e6b51e8f6a..058b5536b11b 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1019,9 +1019,9 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Navigaciju sustavom možete ažurirati u Postavkama"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Razgovor postavljen na prioritetan"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioritetni razgovori će sljedeće:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuje se pri vrhu odjeljka razgovora"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazuje profilnu sliku na zaključanom zaslonu"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioritetni razgovori:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuju se pri vrhu odjeljka razgovora"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazuju profilnu sliku na zaključanom zaslonu"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Prikazuje se kao lebdeći oblačić iznad aplikacija"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Prekida Ne uznemiravaj"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Shvaćam"</string>
@@ -1051,7 +1051,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Zadržite i povucite da biste promijenili raspored kontrola"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Sve su kontrole uklonjene"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Promjene nisu spremljene"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Popis svih kontrola nije se učitao."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kontrole se ne mogu učitati. U aplikaciji <xliff:g id="APP">%s</xliff:g> provjerite da se postavke aplikacije nisu promijenile."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kompatibilne kontrole nisu dostupne"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodavanje kontrolama uređaja"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 64e7011a63a9..257a75f90bab 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tartsa lenyomva, és húzza a vezérlők átrendezéséhez"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Minden vezérlő eltávolítva"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"A rendszer nem mentette a módosításokat"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Nem sikerült betölteni az összes vezérlő listáját."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Más"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Hozzáadás az eszközvezérlőkhöz"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Hozzáadás"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index a337cc22390b..52eee93f5d7b 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Պահեք և քաշեք՝ կառավարման տարրերը վերադասավորելու համար"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Կառավարման բոլոր տարրերը հեռացվեցին"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Փոփոխությունները չեն պահվել"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Չհաջողվեց բեռնել բոլոր կառավարների ցանկը։"</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Այլ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Ավելացրեք սարքերի կառավարման տարրերում"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ավելացնել"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 72fac719f1f1..eab4c2b316e5 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1013,7 +1013,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigasi sistem diupdate. Untuk melakukan perubahan, buka Setelan."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Buka Setelan untuk mengupdate navigasi sistem"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Siaga"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"Percakapan disetel ke prioritas"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"Percakapan ditetapkan jadi prioritas"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Percakapan prioritas akan:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Muncul di atas bagian percakapan"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Menampilkan gambar profil di layar kunci"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tahan &amp; tarik untuk mengatur ulang kontrol"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Semua kontrol dihapus"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Perubahan tidak disimpan"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Daftar semua kontrol tidak dapat dimuat."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kontrol tidak dapat dimuat. Periksa aplikasi <xliff:g id="APP">%s</xliff:g> untuk memastikan setelan aplikasi tidak berubah."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kontrol yang kompatibel tidak tersedia"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Lainnya"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Tambahkan ke kontrol perangkat"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Tambahkan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index a3119ce21498..a0d768ce464a 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1015,7 +1015,7 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Biðstaða"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Samtal sett í forgang"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Forgangssamtöl munu:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Sýna yfir samtalshluta"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Birtast efst í samtalshluta"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Sýna prófílmynd á lásskjá"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Birta sem fljótandi blöðru yfir forritum"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Stöðva „Ónáðið ekki“"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Haltu og dragðu til að endurraða stýringum"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Allar stýringar fjarlægðar"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Breytingar ekki vistaðar"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Ekki tókst að hlaða lista yfir allar stýringar."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Annað"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Bæta við tækjastjórnun"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Bæta við"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b90ae3e5834a..4ed2336697b7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1003,10 +1003,10 @@
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Sposta in basso a sinistra"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Sposta in basso a destra"</string>
<string name="bubble_dismiss_text" msgid="1314082410868930066">"Ignora bolla"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Non utilizzare bolle per la conversazione"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Non mettere la conversazione nella bolla"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatta utilizzando le bolle"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Le nuove conversazioni vengono visualizzate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controlla le bolle in qualsiasi momento"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controlla le bolle quando vuoi"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Tocca Gestisci per disattivare le bolle dall\'app"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Impostazioni <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1016,7 +1016,7 @@
<string name="priority_onboarding_title" msgid="2893070698479227616">"Conversazione impostata come prioritaria"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Le conversazioni prioritarie:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Appaiono in cima alla sezione delle conversazioni"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrano immagine profilo in schermata di blocco"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrano l\'immagine del profilo sulla schermata di blocco"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Vengono mostrate come bolle mobili sopra le app"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrompono la modalità Non disturbare"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tieni premuto e trascina per riordinare i controlli"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Tutti i controlli sono stati rimossi"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Modifiche non salvate"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Impossibile caricare l\'elenco di tutti i controlli."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Impossibile caricare i controlli. Verifica nell\'app <xliff:g id="APP">%s</xliff:g> che le relative impostazioni non siano cambiate."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Controlli compatibili non disponibili"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Aggiungi al controllo dei dispositivi"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Aggiungi"</string>
@@ -1070,7 +1071,7 @@
<string name="controls_error_removed_message" msgid="2885911717034750542">"Impossibile accedere a: <xliff:g id="DEVICE">%1$s</xliff:g>. Verifica nell\'app <xliff:g id="APPLICATION">%2$s</xliff:g> che il controllo sia ancora disponibile e che le impostazioni dell\'app non siano cambiate."</string>
<string name="controls_open_app" msgid="483650971094300141">"Apri app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Impossibile caricare lo stato"</string>
- <string name="controls_error_failed" msgid="960228639198558525">"Errore. Riprova"</string>
+ <string name="controls_error_failed" msgid="960228639198558525">"Errore, riprova"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"In corso"</string>
<string name="controls_added_tooltip" msgid="4842812921719153085">"Tieni premuto il tasto di accensione per visualizzare i nuovi controlli"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Aggiungi controlli"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9d2d0cc973aa..30d4eb4f51de 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1057,7 +1057,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"יש ללחוץ לחיצה ארוכה ולגרור כדי לארגן מחדש את הפקדים"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"כל הפקדים הוסרו"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"השינויים לא נשמרו"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"לא ניתן היה לטעון את הרשימה של כל הפקדים."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"אחר"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"הוספה לפקדי המכשירים"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"הוספה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4f6c7858379c..1b68da178165 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1002,19 +1002,19 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"右上に移動"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"左下に移動"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"右下に移動"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"ふきだしを閉じる"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"バブルを閉じる"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"会話をバブルで表示しない"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"チャットでバブルを使う"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"新しい会話はフローティング アイコン(バブル)として表示されます。タップするとバブルが開きます。ドラッグしてバブルを移動できます。"</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"いつでもバブルを管理"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"このアプリからのバブルをオフにするには、[管理] をタップしてください"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"このアプリからのバブルを OFF にするには、[管理] をタップしてください"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> の設定"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"システム ナビゲーションを更新しました。変更するには [設定] に移動してください。"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"システム ナビゲーションを更新するには [設定] に移動してください"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"スタンバイ"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"優先度を高く設定された会話"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"優先度の高い会話では、次のようになります。"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"優先度の高い会話は、次のように表示されます。"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"会話セクションの一番上にバブルで表示"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"ロック画面にプロフィール写真を表示"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"他のアプリに重ねてフローティング バブルとして表示"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"コントロールを並べ替えるには長押ししてドラッグします"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"すべてのコントロールを削除しました"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"変更が保存されていません"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"全コントロールの一覧を読み込めませんでした。"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"コントロールを読み込めませんでした。<xliff:g id="APP">%s</xliff:g> アプリで、アプリの設定が変更されていないことをご確認ください。"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"互換性のあるコントロールがありません"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"その他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"デバイス コントロールに追加"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"追加"</string>
@@ -1067,7 +1068,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"エラー。再試行しています…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"見つかりませんでした"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"コントロールを使用できません"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"「<xliff:g id="DEVICE">%1$s</xliff:g>」にアクセスできませんでした<xliff:g id="APPLICATION">%2$s</xliff:g> アプリで、コントロールが使用可能な状態でアプリの設定が変更されていないことをご確認ください。"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"「<xliff:g id="DEVICE">%1$s</xliff:g>」にアクセスできませんでした。<xliff:g id="APPLICATION">%2$s</xliff:g> アプリで、コントロールが使用可能な状態でアプリの設定が変更されていないことをご確認ください。"</string>
<string name="controls_open_app" msgid="483650971094300141">"アプリを開く"</string>
<string name="controls_error_generic" msgid="352500456918362905">"ステータスを読み込めません"</string>
<string name="controls_error_failed" msgid="960228639198558525">"エラー: もう一度お試しください"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index aeee416750ed..e1b9245d725b 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"მართვის საშუალებების გადაწყობა შეგიძლიათ მათი ჩავლებით გადატანით"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"მართვის ყველა საშუალება ამოიშალა"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ცვლილებები არ შენახულა"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"მართვის ყველა საშუალების სია ვერ ჩაიტვირთა."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"სხვა"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"მოწყობილ. მართვის საშუალებებში დამატება"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"დამატება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 356526ce9a1d..e6f30ed18f1b 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1002,7 +1002,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Жоғары оң жаққа жылжыту"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Төменгі сол жаққа жылжыту"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Төменгі оң жаққа жылжыту"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Қалқымалы анықтаманы жабу"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Қалқымалы хабарды жабу"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Әңгіменің қалқыма хабары көрсетілмесін"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Қалқыма хабарлар арқылы сөйлесу"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Жаңа әңгімелер қалқыма белгішелер немесе хабарлар түрінде көрсетіледі. Қалқыма хабарды ашу үшін түртіңіз. Жылжыту үшін сүйреңіз."</string>
@@ -1014,8 +1014,8 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Жүйе навигациясын жаңарту үшін \"Параметрлер\" бөліміне өтіңіз."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Күту режимі"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Әңгіме маңызды деп белгіленді"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Маңызды әңгімелердің әрекеті:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Сөйлесу бөлімінің жоғарғы жағында көрсетіледі."</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Маңызды әңгімелер:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Әңгімелер бөлімінің жоғарғы жағында көрсетіледі."</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Профиль суреті құлыптаулы экранда көрсетіледі."</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Қолданбалар терезесінің бергі жағынан қалқыма хабарлар түрінде көрсетіледі."</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"\"Мазаламау\" режимінде көрсетіледі."</string>
@@ -1025,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"Ұлғайту терезесі"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ұлғайту терезесінің басқару элементтері"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Құрылғы басқару виджеттері"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"Жалғанған құрылғыларға басқару элементтерін енгізу"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"Жалғанған құрылғылар үшін басқару виджеттерін қосу"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Құрылғы басқару виджеттерін реттеу"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Басқару элементтерін шығару үшін қуат түймесін басып тұрыңыз."</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Басқару элементтері енгізілетін қолданбаны таңдаңыз"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Басқару элементтерінің ретін өзгерту үшін оларды басып тұрып сүйреңіз."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Барлық басқару элементтері өшірілді."</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Өзгерістер сақталмады."</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Барлық басқару элементі тізімі жүктелмеді."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Басқару элементтері жүктелмеді. Қолданба параметрлерінің өзгермегенін тексеру үшін <xliff:g id="APP">%s</xliff:g> қолданбасын қараңыз."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Үйлесімді басқару элементтері қолжетімді емес."</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Басқа"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Құрылғы басқару виджеттеріне қосу"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Енгізу"</string>
@@ -1066,8 +1067,8 @@
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Қате, әрекет қайталануда…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылмады"</string>
- <string name="controls_error_removed_title" msgid="1207794911208047818">"Басқару элементтері қолжетімді емес"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ашылмады. Басқару элементтерінің әлі қолжетімді екенін және қолданба параметрлерінің өзгермегенін тексеру үшін <xliff:g id="APPLICATION">%2$s</xliff:g> қолданбасын қараңыз."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Басқару виджеті қолжетімсіз"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ашылмады. Басқару виджетінің әлі қолжетімді екенін және қолданба параметрлерінің өзгермегенін тексеру үшін <xliff:g id="APPLICATION">%2$s</xliff:g> қолданбасын қараңыз."</string>
<string name="controls_open_app" msgid="483650971094300141">"Қолданбаны ашу"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Күйді жүктеу мүмкін емес."</string>
<string name="controls_error_failed" msgid="960228639198558525">"Қате шықты. Қайталап көріңіз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index b0f90e2b2869..687508ea53d8 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"ចុច​ឱ្យ​ជាប់ រួចអូស​ដើម្បី​រៀបចំ​ផ្ទាំងគ្រប់គ្រង​ឡើងវិញ"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"បាន​ដកផ្ទាំងគ្រប់គ្រងទាំងអស់ហើយ"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"មិនបាន​រក្សាទុក​ការផ្លាស់ប្ដូរទេ"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"មិនអាច​ផ្ទុក​បញ្ជី​នៃការគ្រប់គ្រង​ទាំងអស់​បានទេ។"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"មិនអាចផ្ទុក​ការគ្រប់គ្រង​បានទេ។ សូមពិនិត្យមើល​កម្មវិធី <xliff:g id="APP">%s</xliff:g> ដើម្បីធ្វើឱ្យប្រាកដថា​ការកំណត់កម្មវិធី​មិនបានផ្លាស់ប្ដូរ។"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"មិនអាចប្រើ​ការគ្រប់គ្រង​ដែលត្រូវគ្នា​បានទេ"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ផ្សេងៗ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"បញ្ចូល​ទៅក្នុងផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"បញ្ចូល"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index ed5342554913..7659b4594ce2 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -510,8 +510,7 @@
<string name="clear_all_notifications_text" msgid="348312370303046130">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ನಿರ್ವಹಿಸಿ"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"ಇತಿಹಾಸ"</string>
- <!-- no translation found for notification_section_header_incoming (850925217908095197) -->
- <skip />
+ <string name="notification_section_header_incoming" msgid="850925217908095197">"ಹೊಸತು"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"ನಿಶ್ಶಬ್ದ"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"ಸಂಭಾಷಣೆಗಳು"</string>
@@ -1046,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"ನಿಯಂತ್ರಣಗಳನ್ನು ಮರುಹೊಂದಿಸಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಮತ್ತು ಡ್ರ್ಯಾಗ್‌ ಮಾಡಿ"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"ಎಲ್ಲಾ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ಬದಲಾವಣೆಗಳನ್ನು ಉಳಿಸಲಾಗಿಲ್ಲ"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"ಎಲ್ಲಾ ನಿಯಂತ್ರಣಗಳ ಪಟ್ಟಿಯನ್ನು ಲೋಡ್ ಮಾಡಲು ಆಗಲಿಲ್ಲ."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ಇತರ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ಸಾಧನ ನಿಯಂತ್ರಣಗಳಿಗೆ ಸೇರಿಸಿ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ಸೇರಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index a27f4f723a0c..cb74d86184f3 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1003,7 +1003,7 @@
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"왼쪽 하단으로 이동"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"오른쪽 하단으로 이동"</string>
<string name="bubble_dismiss_text" msgid="1314082410868930066">"대화창 닫기"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"대화를 대화창으로 표시하지 않음"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"대화를 대화창으로 표시하지 않기"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"대화창으로 채팅하기"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"새로운 대화가 플로팅 아이콘인 대화창으로 표시됩니다. 대화창을 열려면 탭하세요. 드래그하여 이동할 수 있습니다."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"언제든지 대화창을 제어하세요"</string>
@@ -1014,7 +1014,7 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"설정으로 이동하여 시스템 탐색을 업데이트하세요."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"대기"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"대화가 우선순위 대화로 설정됨"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"우선순위 대화에서 다음과 같은 동작을 합니다."</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"우선순위 대화는 다음과 같이 표시됩니다."</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"대화 섹션의 상단에 표시"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"잠금 화면에서 프로필 사진 표시"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"앱 상단에서 플로팅 대화창으로 표시"</string>
@@ -1025,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"기기 컨트롤"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"연결된 기기의 컨트롤을 추가합니다."</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"연결된 기기의 컨트롤을 추가하세요."</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"기기 컨트롤 설정"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"전원 버튼을 길게 눌러 컨트롤에 액세스하세요."</string>
<string name="controls_providers_title" msgid="6879775889857085056">"컨트롤을 추가할 앱을 선택하세요"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"길게 누르고 드래그하여 컨트롤 재정렬"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"모든 컨트롤 삭제됨"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"변경사항이 저장되지 않음"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"전체 컨트롤 목록을 로드할 수 없습니다."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"컨트롤을 로드할 수 없습니다. <xliff:g id="APP">%s</xliff:g> 앱에서 설정이 변경되지 않았는지 확인하세요."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"호환 컨트롤을 사용할 수 없습니다."</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"기타"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"기기 컨트롤에 추가"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"추가"</string>
@@ -1067,7 +1068,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"오류 발생, 다시 시도 중…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"찾을 수 없음"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"컨트롤을 사용할 수 없음"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>에 액세스할 수 없습니다. <xliff:g id="APPLICATION">%2$s</xliff:g> 앱에서 컨트롤을 계속 사용할 수 있는지와 앱 설정이 변경되지 않았는지 확인하세요."</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>에 액세스할 수 없습니다. <xliff:g id="APPLICATION">%2$s</xliff:g> 앱에서 컨트롤을 계속 사용할 수 있는지, 앱 설정이 변경되지는 않았는지 확인하세요."</string>
<string name="controls_open_app" msgid="483650971094300141">"앱 열기"</string>
<string name="controls_error_generic" msgid="352500456918362905">"통계를 로드할 수 없음"</string>
<string name="controls_error_failed" msgid="960228639198558525">"오류. 다시 시도하세요."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 74f43e870da7..839bb503c70f 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1003,11 +1003,11 @@
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Төмөнкү сол жакка жылдыруу"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Төмөнкү оң жакка жылдырыңыз"</string>
<string name="bubble_dismiss_text" msgid="1314082410868930066">"Калкып чыкма билдирмени жабуу"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Жазышуу калкып чыкма билдирмеде көрүнбөсүн"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Жазышууда калкып чыкма билдирмелер көрүнбөсүн"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Калкып чыкма билдирмелер аркылуу маектешүү"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Жаңы жазышуулар калкыма сүрөтчөлөр же калкып чыкма билдирмелер түрүндө көрүнөт. Калкып чыкма билдирмелерди ачуу үчүн таптап коюңуз. Жылдыруу үчүн сүйрөңүз."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Калкып чыкма билдирмелерди каалаган убакта көзөмөлдөңүз"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Бул колдонмодогу калкып чыкма билдирмелерди өчүрүү үчүн \"Башкарууну\" басыңыз"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Бул колдонмодогу калкып чыкма билдирмелерди өчүрүү үчүн, \"Башкарууну\" басыңыз"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Түшүндүм"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> жөндөөлөрү"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Тутум чабыттоосу жаңырды. Өзгөртүү үчүн, Жөндөөлөргө өтүңүз."</string>
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Көшүү режими"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Жазышуу маанилүү болуп коюлду"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Маанилүү жазышуулардын төмөнкүдөй артыкчылыктары бар:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Жазышуу бөлүмүнүн үстүндө көрсөтүү"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Профилдин сүрөтүн кулпуланган экранда көрсөтүү"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Жазышуулар тизмесинин үстүндө көрүнөт"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Профилдин сүрөтү кулпуланган экранда көрүнөт"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Калкым чыкма билдирме катары көрсөтүү"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"\"Тынчымды алба\" режими үзгүлтүккө учурайт"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Түшүндүм"</string>
@@ -1025,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"Чоңойтуу терезеси"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Чоңойтуу терезесин башкаруу каражаттары"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Түзмөктү башкаруу элементтери"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"Байланышкан түзмөктөрүңүздү башкаруу элементтерин кошуңуз"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"Байланышкан түзмөктөрүңүздү башкаруу элементтерин кошосуз"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Түзмөктү башкаруу элементтерин жөндөө"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Көзөмөлдөргө өтүү үчүн, күйгүзүү/өчүрүү баскычын басып туруңуз"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Башкаруу элементтери кошула турган колдонмону тандаңыз"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Башкаруу элементтеринин иретин өзгөртүү үчүн, кармап туруп, сүйрөңүз"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Бардык башкаруу элементтери өчүрүлдү"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Өзгөртүүлөр сакталган жок"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Бардык көзөмөлдөрдүн тизмеси жүктөлгөн жок."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Башка"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Түзмөктү башкаруу элементтерине кошуу"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Кошуу"</string>
@@ -1066,8 +1069,8 @@
<string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ката, дагы аракет жасалууда…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылган жок"</string>
- <string name="controls_error_removed_title" msgid="1207794911208047818">"Көзөмөл жеткиликтүү эмес"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүнө кирүү мүмкүнчүлүгү жок. <xliff:g id="APPLICATION">%2$s</xliff:g> колдонмосуна өтүп, көзөмөл жеткиликтүү экенин жана колдонмонун жөндөөлөрү өзгөрбөгөнүн текшериңиз."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Башкара албайсыз"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүн пайдалана албайсыз. Аны <xliff:g id="APPLICATION">%2$s</xliff:g> колдонмосунан башкарууга мүмкүн же мүмкүн эместигин, ошондой эле колдонмонун жөндөөлөрүнүн өзгөрүлбөгөнүн текшериңиз."</string>
<string name="controls_open_app" msgid="483650971094300141">"Колдонмону ачуу"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Абалы жүктөлгөн жок"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Ката, кайталап көрүңүз"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 0fe47aab6e7c..8d44a9cf7997 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1002,7 +1002,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ຍ້າຍຂວາເທິງ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ຍ້າຍຊ້າຍລຸ່ມ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ຍ້າຍຂວາລຸ່ມ"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"ປິດ bubble ໄວ້"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"ປິດຟອງໄວ້"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ຢ່າໃຊ້ຟອງໃນການສົນທະນາ"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ສົນທະນາໂດຍໃຊ້ຟອງ"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"ການສົນທະນາໃໝ່ຈະປາກົດເປັນໄອຄອນ ຫຼື ຟອງແບບລອຍ. ແຕະເພື່ອເປີດຟອງ. ລາກເພື່ອຍ້າຍມັນ."</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"ກົດຄ້າງໄວ້ເພື່ອຈັດຮຽງການຄວບຄຸມຄືນໃໝ່"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"ລຶບການຄວບຄຸມທັງໝົດອອກແລ້ວ"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ບໍ່ໄດ້ບັນທຶກການປ່ຽນແປງໄວ້"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"ບໍ່ສາມາດໂຫຼດລາຍຊື່ການຄວບຄຸມທັງໝົດໄດ້."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"ບໍ່ສາມາດໂຫຼດການຄວບຄຸມໄດ້. ກວດສອບແອັບ <xliff:g id="APP">%s</xliff:g> ເພື່ອໃຫ້ແນ່ໃຈວ່າຍັງບໍ່ມີການປ່ຽນແປງການຕັ້ງຄ່າແອັບເທື່ອ."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"ບໍ່ມີການຄວບຄຸມທີ່ໃຊ້ຮ່ວມກັນທີ່ສາມາດໃຊ້ໄດ້"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ອື່ນໆ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ເພີ່ມໃສ່ການຄວບຄຸມອຸປະກອນ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ເພີ່ມ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 59cab5795f13..7988dc4d741e 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1057,7 +1057,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Norėdami pertvarkyti valdiklius, vilkite laikydami nuspaudę"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Visi valdikliai pašalinti"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Pakeitimai neišsaugoti"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Nepavyko įkelti visų valdiklių sąrašo."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Kita"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Pridėjimas prie įrenginio valdiklių"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Pridėti"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index bc157026e745..2bffca24b31b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1011,7 +1011,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nerādīt sarunu burbuļos"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Tērzēšana, izmantojot burbuļus"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Jaunas sarunas tiek rādītas kā peldošas ikonas vai burbuļi. Pieskarieties, lai atvērtu burbuli. Velciet, lai to pārvietotu."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Pārvaldīt burbuļus jebkurā laikā"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Allaž pārvaldīt burbuļus"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Pieskarieties pogai “Pārvaldīt”, lai izslēgtu burbuļus no šīs lietotnes."</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Labi"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Lietotnes <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> iestatījumi"</string>
@@ -1051,7 +1051,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Lai pārkārtotu vadīklas, turiet un velciet tās"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Visas vadīklas ir noņemtas"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Izmaiņas nav saglabātas."</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Nevarēja ielādēt sarakstu ar visām vadīklām."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Cita"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Pievienošana ierīču vadīklām"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Pievienot"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 09e7ff17714f..561380cdf91a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -994,7 +994,7 @@
<string name="bubbles_settings_button_description" msgid="7324245408859877545">"Поставки за балончињата за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Прелевање"</string>
<string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Додајте назад во stack"</string>
- <string name="manage_bubbles_text" msgid="6856830436329494850">"Управување"</string>
+ <string name="manage_bubbles_text" msgid="6856830436329494850">"Управувајте"</string>
<string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> од <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
<string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> од <xliff:g id="APP_NAME">%2$s</xliff:g> и уште <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
<string name="bubble_accessibility_action_move" msgid="3185080443743819178">"Премести"</string>
@@ -1014,9 +1014,9 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Одете во „Поставки“ за да ја ажурирате навигацијата на системот"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Подготвеност"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Разговорот е поставен како приоритетен"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Приорететните разговори ќе:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Се прикажува најгоре во делот со разговори"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Се прикажува профилна слика на заклучен екран"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Приоритетните разговори:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"ќе се прикажуваат најгоре во делот со разговори;"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"ќе прикажуваат профилна слика на заклучен екран."</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Се појавува како лебдечко балонче врз апликациите"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Прекинува „Не вознемирувај“"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Сфатив"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Задржете и влечете за да ги преуредите контролите"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Сите контроли се отстранети"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Промените не се зачувани"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Не можеше да се вчита списокот со сите контроли."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Контролите не можеше да се вчитаат. Проверете ја апликацијата <xliff:g id="APP">%s</xliff:g> за да се уверите дека поставките за апликацијата не се променети."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Нема компатибилни контроли"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друга"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Додајте во контроли за уредите"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
@@ -1067,8 +1068,8 @@
<string name="controls_error_retryable" msgid="864025882878378470">"Грешка, повторен обид…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е најдено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е достапна"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"Не може да се пристапи до <xliff:g id="DEVICE">%1$s</xliff:g>. Проверете ја апликацијата <xliff:g id="APPLICATION">%2$s</xliff:g> за да се осигурите дека контролата е сè уште достапна и дека поставките за апликацијата не се сменети."</string>
- <string name="controls_open_app" msgid="483650971094300141">"Отвори ја апликација"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Не може да се пристапи до <xliff:g id="DEVICE">%1$s</xliff:g>. Проверете ја апликацијата <xliff:g id="APPLICATION">%2$s</xliff:g> за да се уверите дека контролата е сѐ уште достапна и дека поставките за апликацијата не се сменети."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Отвори апликација"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Не може да се вчита статусот"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Грешка, обидете се повторно"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Во тек"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index e4d4ba407732..bf4f902f3bd6 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -510,8 +510,7 @@
<string name="clear_all_notifications_text" msgid="348312370303046130">"എല്ലാം മായ്‌ക്കുക"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"മാനേജ് ചെയ്യുക"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"ചരിത്രം"</string>
- <!-- no translation found for notification_section_header_incoming (850925217908095197) -->
- <skip />
+ <string name="notification_section_header_incoming" msgid="850925217908095197">"പുതിയത്"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"നിശബ്‌ദം"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"അറിയിപ്പുകൾ"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"സംഭാഷണങ്ങൾ"</string>
@@ -1009,7 +1008,7 @@
<string name="bubbles_user_education_description" msgid="1160281719576715211">"പുതിയ സംഭാഷണങ്ങൾ ഫ്ലോട്ടിംഗ് ഐക്കണുകളോ ബബിളുകളോ ആയി ദൃശ്യമാവുന്നു. ബബിൾ തുറക്കാൻ ടാപ്പ് ചെയ്യൂ. ഇത് നീക്കാൻ വലിച്ചിടുക."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"ബബിളുകൾ ഏതുസമയത്തും നിയന്ത്രിക്കുക"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"ഈ ആപ്പിൽ നിന്നുള്ള ബബിളുകൾ ഓഫാക്കാൻ മാനേജ് ചെയ്യുക ടാപ്പ് ചെയ്യുക"</string>
- <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"ലഭിച്ചു"</string>
+ <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"മനസ്സിലായി"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ക്രമീകരണം"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"സിസ്‌റ്റം നാവിഗേഷൻ അപ്‌ഡേറ്റ് ചെയ്‌തു. മാറ്റങ്ങൾ വരുത്താൻ ക്രമീകരണത്തിലേക്ക് പോവുക."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"സിസ്‌റ്റം നാവിഗേഷൻ അപ്‌ഡേറ്റ് ചെയ്യാൻ ക്രമീകരണത്തിലേക്ക് പോവുക"</string>
@@ -1026,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ നിയന്ത്രണങ്ങൾ"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"ഉപകരണ നിയന്ത്രണങ്ങൾ"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"നിങ്ങളുടെ കണക്റ്റ് ചെയ്ത ഉപകരണങ്ങൾക്ക് നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"കണക്റ്റ് ചെയ്ത ഉപകരണങ്ങൾക്ക് നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ഉപകരണ നിയന്ത്രണങ്ങൾ സജ്ജീകരിക്കുക"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"നിങ്ങളുടെ നിയന്ത്രണങ്ങൾ ആക്‌സസ് ചെയ്യാൻ പവർ ബട്ടണിൽ പിടിക്കുക"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"നിയന്ത്രണങ്ങൾ ചേർക്കാൻ ആപ്പ് തിരഞ്ഞെടുക്കുക"</string>
@@ -1046,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"നിയന്ത്രണങ്ങൾ പുനഃക്രമീകരിക്കാൻ അമർത്തിപ്പിടിച്ച് വലിച്ചിടുക"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"എല്ലാ നിയന്ത്രണങ്ങളും നീക്കം ചെയ്തു"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"മാറ്റങ്ങൾ സംരക്ഷിച്ചിട്ടില്ല"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"എല്ലാ നിയന്ത്രണങ്ങളുടെയും ലിസ്റ്റ് ലോഡ് ചെയ്യാനായില്ല."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"മറ്റുള്ളവ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ഉപകരണ നിയന്ത്രണങ്ങളിലേക്ക് ചേർക്കുക"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ചേർക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 4ab58f089e24..0420ffa03969 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Хяналтуудыг дахин засварлахын тулд дараад чирнэ үү"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Бүх хяналтыг хассан"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Өөрчлөлтийг хадгалаагүй"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Бүх хяналтын жагсаалтыг ачаалж чадсангүй."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Хяналтыг ачаалж чадсангүй. Аппын тохиргоог өөрчлөөгүй эсэхийг нягтлахын тулд <xliff:g id="APP">%s</xliff:g> аппыг шалгана уу."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Тохирох хяналт байхгүй"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Бусад"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Төхөөрөмжийн хяналт руу нэмэх"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Нэмэх"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d49f46d840b2..c080211b9cc5 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -510,8 +510,7 @@
<string name="clear_all_notifications_text" msgid="348312370303046130">"सर्व साफ करा"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थापित करा"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
- <!-- no translation found for notification_section_header_incoming (850925217908095197) -->
- <skip />
+ <string name="notification_section_header_incoming" msgid="850925217908095197">"नवीन"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"सायलंट"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"सूचना"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"संभाषणे"</string>
@@ -1046,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"नियंत्रणांची पुनर्रचना करण्यासाठी धरून ठेवा आणि ड्रॅग करा"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"सर्व नियंत्रणे काढून टाकली आहेत"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"बदल सेव्ह केले गेले नाहीत"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"सर्व नियंत्रणांची सूची लोड करता आली नाही."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"नियंत्रणे लोड करता अली नाहीत. ॲपची सेटिंग्ज बदलली नसल्याची खात्री करण्यासाठी <xliff:g id="APP">%s</xliff:g> ॲप तपासा."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"कंपॅटिबल नियंत्रणे उपलब्ध नाहीत"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"इतर"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"डिव्हाइस नियंत्रणांमध्ये जोडा"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"जोडा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index be17eade57a1..8514403f95e4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Tunggu sedia"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Perbualan ditetapkan kepada keutamaan"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Perbualan keutamaan akan:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Tunjukkan di atas bahagian perbualan"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Tunjukkan gambar profil pada skrin kunci"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Muncul di atas bahagian perbualan"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Memaparkan gambar profil pada skrin kunci"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Dipaparkan sebagai gelembung terapung di atas apl"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ganggu ciri Jangan Ganggu"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tahan &amp; seret untuk mengatur semula kawalan"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Semua kawalan dialih keluar"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Perubahan tidak disimpan"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Senarai semua kawalan tidak dapat dimuatkan."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kawalan tidak dapat dimuatkan. Semak apl <xliff:g id="APP">%s</xliff:g> untuk memastikan bahawa tetapan apl tidak berubah."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kawalan serasi tidak tersedia"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Lain-lain"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Tambahkan pada kawalan peranti"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Tambah"</string>
@@ -1065,7 +1066,7 @@
<string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ralat, mencuba semula…"</string>
- <string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemui"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kawalan tidak tersedia"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"Tidak dapat mengakses <xliff:g id="DEVICE">%1$s</xliff:g>. Periksa apl <xliff:g id="APPLICATION">%2$s</xliff:g> untuk memastikan kawalan masih tersedia dan tetapan apl tidak berubah."</string>
<string name="controls_open_app" msgid="483650971094300141">"Buka apl"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index eaf4157ff4e1..32c72ef51c6e 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"ထိန်းချုပ်မှုများ ပြန်စီစဉ်ရန် ဖိပြီးဆွဲပါ"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"ထိန်းချုပ်မှုအားလုံး ဖယ်ရှားလိုက်သည်"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"အပြောင်းအလဲများကို သိမ်းမထားပါ"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"ထိန်းချုပ်မှုအားလုံး၏ စာရင်းကို ဖွင့်၍မရပါ။"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"ထိန်းချုပ်မှုများကို ဖွင့်၍မရပါ။ အက်ပ်ဆက်တင်များ ပြောင်းမထားကြောင်း သေချာစေရန် <xliff:g id="APP">%s</xliff:g> အက်ပ်ကို စစ်ဆေးပါ။"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"ကိုက်ညီသော ထိန်းချုပ်မှုများကို မရရှိနိုင်ပါ"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"အခြား"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"စက်ထိန်းစနစ်သို့ ထည့်ရန်"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ထည့်ရန်"</string>
@@ -1066,7 +1067,7 @@
<string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"မှားသွားသည်၊ ပြန်စမ်းနေသည်…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"မတွေ့ပါ"</string>
- <string name="controls_error_removed_title" msgid="1207794911208047818">"ထိန်းချုပ်၍ မရတော့ပါ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"ထိန်းချုပ်မှု မရနိုင်ပါ"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> အသုံးပြု၍ မရပါ။ ထိန်းချုပ်၍ ရသေးကြောင်းနှင့် အက်ပ်ဆက်တင်များ ပြောင်းမထားကြောင်း သေချာစေရန် <xliff:g id="APPLICATION">%2$s</xliff:g> အက်ပ်ကို စစ်ဆေးပါ။"</string>
<string name="controls_open_app" msgid="483650971094300141">"အက်ပ်ဖွင့်ရန်"</string>
<string name="controls_error_generic" msgid="352500456918362905">"အခြေအနေကို ဖွင့်၍မရပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index aee2dd288262..8a134ee4a7a5 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1013,10 +1013,10 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigeringen er oppdatert. For å gjøre endringer, gå til Innstillinger."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gå til Innstillinger for å oppdatere systemnavigeringen"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ventemodus"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"Samtalen er satt som prioritert"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"Samtalen er prioritert"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Dette skjer med prioriterte samtaler:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Vis øverst i samtaledelen"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Vis profilbildet på låseskjermen"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"De vises øverst i samtaledelen."</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Profilbildet vises på låseskjermen."</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Vises som en svevende boble over apper"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Overstyr «Ikke forstyrr»"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Greit"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold og dra for å flytte kontroller"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Alle kontroller er fjernet"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Endringene er ikke lagret"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Listen over alle kontroller kunne ikke lastes inn."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kunne ikke laste inn kontrollene. Sjekk <xliff:g id="APP">%s</xliff:g>-appen for å sjekke at appinnstillingene ikke er endret."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Kompatible kontroller er ikke tilgjengelige"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Annet"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Legg til i enhetsstyring"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Legg til"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index fda85ccb542c..0091d5ee4f55 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -510,8 +510,7 @@
<string name="clear_all_notifications_text" msgid="348312370303046130">"सबै हटाउनुहोस्"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थित गर्नुहोस्"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
- <!-- no translation found for notification_section_header_incoming (850925217908095197) -->
- <skip />
+ <string name="notification_section_header_incoming" msgid="850925217908095197">"नयाँ"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"मौन"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"सूचनाहरू"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"वार्तालापहरू"</string>
@@ -1008,16 +1007,16 @@
<string name="bubbles_user_education_title" msgid="5547017089271445797">"बबलहरू प्रयोग गरी कुराकानी गर्नुहोस्"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"नयाँ वार्तालापहरू तैरने आइकन वा बबलका रूपमा देखिन्छन्। बबल खोल्न ट्याप गर्नुहोस्। बबल सार्न सो बबललाई ड्र्याग गर्नुहोस्।"</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"जुनसुकै बेला बबलहरू नियन्त्रण गर्नुहोस्"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"यो अनुप्रयोगबाट आएका बबलहरू निष्क्रिय पार्न व्यवस्थापन गर्नुहोस् नामक बटनमा ट्याप गर्नुहोस्"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"यो एपबाट आएका बबलहरू अफ गर्न \"व्यवस्थापन गर्नुहोस्\" बटनमा ट्याप गर्नुहोस्"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"बुझेँ"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> का सेटिङहरू"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"प्रणालीको नेभिगेसन अद्यावधिक गरियो। परिवर्तन गर्न सेटिङमा जानुहोस्।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"प्रणालीको नेभिगेसन अद्यावधिक गर्न सेटिङमा जानुहोस्"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्ट्यान्डबाई"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"वार्तालापको प्राथमिकता निर्धारण गरी महत्त्वपूर्ण बनाइयो"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"महत्वपूर्ण वार्तालापहरू यहाँ देखिने छन्:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"वार्तालाप खण्डको सिरानमा देखाइयोस्"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"लक स्क्रिनमा प्रोफाइल तस्बिर देखाइयोस्"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"वार्तालापको प्राथमिकता निर्धारण गरी \"महत्त्वपूर्ण\" बनाइयो"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"महत्वपूर्ण वार्तालापहरू:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"वार्तालाप खण्डको सिरानमा देखिने छन्"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"लक स्क्रिनमा प्रोफाइल तस्बिर देखाउने छन्"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"एपहरूमाथि तैरिने बबलका रूपमा देखाइयोस्"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"बाधा नपुऱ्याउनुहोस् मोडलाई बेवास्ता गरियोस्"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"बुझेँ"</string>
@@ -1046,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"नियन्त्रणहरूको क्रम मिलाउन तिनलाई थिचेर ड्र्याग गर्नुहोस्"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"सबै नियन्त्रणहरू हटाइए"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"परिवर्तनहरू सुरक्षित गरिएका छैनन्"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"सबै नियन्त्रणहरूको सूची लोड गर्न सकिएन।"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"नियन्त्रण सुविधाहरू लोड गर्न सकिएन। <xliff:g id="APP">%s</xliff:g> एपका सेटिङ परिवर्तन गरिएका छैनन् भन्ने कुरा सुनिश्चित गर्न यो एप जाँच्नुहोस्।"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"मिल्दा नियन्त्रण सुविधाहरू उपलब्ध छैनन्"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"यन्त्र नियन्त्रण गर्ने विजेटहरूको सूचीमा थप्नुहोस्"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"थप्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 87f072b9e7dd..23d2d1cf75c8 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1014,7 +1014,7 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ga naar Instellingen om de systeemnavigatie te updaten"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stand-by"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Gesprek ingesteld als prioriteit"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Bij prioriteitsgesprekken gebeurt het volgende:"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioriteitsgesprekken:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Worden bovenaan het gespreksgedeelte weergegeven"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Tonen profielafbeelding op vergrendelscherm"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Worden als zwevende ballon weergegeven vóór apps"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Houd vast en sleep om de bedieningselementen opnieuw in te delen"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Alle bedieningselementen verwijderd"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Wijzigingen zijn niet opgeslagen"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Kan lijst met alle bedieningselementen niet laden."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Bedieningselementen kunnen niet worden geladen. Check de <xliff:g id="APP">%s</xliff:g>-app om na te gaan of de app-instellingen niet zijn gewijzigd."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Geen geschikte bedieningselementen beschikbaar."</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Overig"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Toevoegen aan apparaatbediening"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Toevoegen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 426bd2ec1ada..6fa9699192c7 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -510,8 +510,7 @@
<string name="clear_all_notifications_text" msgid="348312370303046130">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"ଇତିହାସ"</string>
- <!-- no translation found for notification_section_header_incoming (850925217908095197) -->
- <skip />
+ <string name="notification_section_header_incoming" msgid="850925217908095197">"ନୂଆ"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"ନୀରବ"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string>
@@ -1014,8 +1013,8 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ ହୋଇଛି। ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ, ସେଟିଂସ୍‌କୁ ଯାଆନ୍ତୁ।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ କରିବା ପାଇଁ ସେଟିଂସ୍‍କୁ ଯାଆନ୍ତୁ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ଷ୍ଟାଣ୍ଡବାଏ"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"ବାର୍ତ୍ତାଳାପ ପ୍ରାଥମିକରେ ସେଟ୍ କରାଯାଇଛି"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ପ୍ରାଥମିକ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଏଠାରେ ଦେଖାଯିବ:"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"ବାର୍ତ୍ତାଳାପ ପ୍ରାଥମିକତାରେ ସେଟ୍ କରାଯାଇଛି"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ପ୍ରାଥମିକତା ଦିଆଯାଇଥିବା ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଏଠାରେ ଦେଖାଯିବ:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"ବାର୍ତ୍ତାଳାପ ବିଭାଗର ଶୀର୍ଷରେ ଦେଖାନ୍ତୁ"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"ଲକ୍ ସ୍କ୍ରିନରେ ପ୍ରୋଫାଇଲ୍ ଛବି ଦେଖାନ୍ତୁ"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ଆପଗୁଡ଼ିକ ଉପରେ ଫ୍ଲୋଟିଂ ବବଲ୍ ପରି ଦେଖାଯିବ"</string>
@@ -1026,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"ଆପଣଙ୍କ ସଂଯୁକ୍ତ ଥିବା ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣ ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"ଆପଣଙ୍କ ସଂଯୁକ୍ତ ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣ ଯୋଗ କରନ୍ତୁ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"ଆପଣଙ୍କ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବାକୁ ପାୱାର ବଟନକୁ ଧରି ରଖନ୍ତୁ"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଯୋଗ କରିବାକୁ ଆପ୍ ବାଛନ୍ତୁ"</string>
@@ -1046,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ପୁଣି ସଜାଇବାକୁ ସେଗୁଡ଼ିକୁ ଧରି ଟାଣନ୍ତୁ"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"ସମସ୍ତ ନିୟନ୍ତ୍ରଣ କାଢ଼ି ଦିଆଯାଇଛି"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ପରିବର୍ତ୍ତନଗୁଡ଼ିକ ସେଭ୍ କରାଯାଇନାହିଁ"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"ସବୁ ନିୟନ୍ତ୍ରଣର ତାଲିକା ଲୋଡ୍ କରିପାରିଲା ନାହିଁ।"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଲୋଡ୍ କରାଯାଇପାରିଲା ନାହିଁ। ଆପ୍ ସେଟିଂସ୍ ପରିବର୍ତ୍ତନ ହୋଇନାହିଁ ବୋଲି ନିଶ୍ଚିତ କରିବାକୁ <xliff:g id="APP">%s</xliff:g> ଆପ୍ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"ସୁସଙ୍ଗତ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ଅନ୍ୟ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକରେ ଯୋଗ କରନ୍ତୁ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ଯୋଗ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index ccafc49614bb..9a93749d3e54 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -510,7 +510,7 @@
<string name="clear_all_notifications_text" msgid="348312370303046130">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"ਇਤਿਹਾਸ"</string>
- <string name="notification_section_header_incoming" msgid="850925217908095197">"ਨਵਾਂ"</string>
+ <string name="notification_section_header_incoming" msgid="850925217908095197">"ਨਵੀਆਂ"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"ਸ਼ਾਂਤ"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"ਸੂਚਨਾਵਾਂ"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"ਗੱਲਾਂਬਾਤਾਂ"</string>
@@ -1014,7 +1014,7 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ਸਿਸਟਮ ਨੈਵੀਗੇਸ਼ਨ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਲਈ ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ਸਟੈਂਡਬਾਈ"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"ਗੱਲਬਾਤ ਨੂੰ ਤਰਜੀਹੀ ਗੱਲਬਾਤ ਵਜੋਂ ਸੈੱਟ ਕੀਤਾ ਗਿਆ"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ਤਰਜੀਹੀ ਗੱਲਾਂਬਾਤਾਂ ਇਹ ਹੋਣਗੀਆਂ:"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ਤਰਜੀਹੀ ਗੱਲਾਂਬਾਤਾਂ ਨਾਲ ਇਹ ਵਿਹਾਰ ਹੋਵੇਗਾ:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"ਗੱਲਬਾਤ ਸੈਕਸ਼ਨ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਓ"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਦਿਖਾਓ"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ਐਪਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਫਲੋਟਿੰਗ ਬਬਲ ਵਜੋਂ ਦਿਸਦੀਆਂ ਹਨ"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"ਕੰਟਰੋਲਾਂ ਨੂੰ ਮੁੜ-ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ ਫੜ੍ਹ ਕੇ ਘਸੀਟੋ"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"ਸਾਰੇ ਕੰਟਰੋਲ ਹਟਾਏ ਗਏ"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ਤਬਦੀਲੀਆਂ ਨੂੰ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"ਸਾਰੇ ਕੰਟਰੋਲਾਂ ਦੀ ਸੂਚੀ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"ਕੰਟਰੋਲਾਂ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਇਹ ਪੱਕਾ ਕਰਨ ਲਈ <xliff:g id="APP">%s</xliff:g> ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ ਕਿ ਐਪ ਸੈਟਿੰਗਾਂ ਨਹੀਂ ਬਦਲੀਆਂ ਹਨ।"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"ਕੋਈ ਅਨੁਰੂਪ ਕੰਟਰੋਲ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ਹੋਰ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"ਡੀਵਾਈਸ ਕੰਟਰੋਲਾਂ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"ਸ਼ਾਮਲ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index cf63b1122da7..45dbcba43eec 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1057,7 +1057,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Przytrzymaj i przeciągnij, aby przestawić elementy sterujące"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Usunięto wszystkie elementy sterujące"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Zmiany nie zostały zapisane"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Nie udało się wczytać listy elementów sterujących."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Nie udało się wczytać elementów sterujących. Sprawdź aplikację <xliff:g id="APP">%s</xliff:g>, aby upewnić się, że jej ustawienia się nie zmieniły."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Zgodne elementy sterujące niedostępne"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Inne"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodaj do sterowania urządzeniami"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
@@ -1079,7 +1080,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"Błąd, próbuję jeszcze raz…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie znaleziono"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Element jest niedostępny"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"Nie udało się połączyć z urządzeniem: <xliff:g id="DEVICE">%1$s</xliff:g>. Sprawdź aplikację <xliff:g id="APPLICATION">%2$s</xliff:g>, aby upewnić się, że element sterujący jest wciąż dostępny i ustawienia aplikacji się nie zmieniły."</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nie udało się połączyć z urządzeniem <xliff:g id="DEVICE">%1$s</xliff:g>. Sprawdź aplikację <xliff:g id="APPLICATION">%2$s</xliff:g>, aby upewnić się, że element sterujący jest wciąż dostępny i ustawienia aplikacji się nie zmieniły."</string>
<string name="controls_open_app" msgid="483650971094300141">"Otwórz aplikację"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Nie udało się wczytać stanu"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Błąd, spróbuj ponownie"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 9b3976eaffb8..cd436ddd3cf4 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"A conversa foi definida como prioritária"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"As conversas prioritárias:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecer na parte superior da seção de conversa"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrar foto do perfil na tela de bloqueio"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecem na parte superior da seção de conversa"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostram a foto do perfil na tela de bloqueio"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecer como balões flutuantes sobre outros apps"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interromper o \"Não perturbe\""</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Ok"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Toque no controle, mantenha-o pressionado e arraste para reorganizar as posições."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Todos os controles foram removidos"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"As mudanças não foram salvas"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Não foi possível carregar a lista de controles."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adicionar aos controles do dispositivo"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 55b5af121f37..8339d6a88012 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -104,7 +104,7 @@
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar toques no ecrã"</string>
<string name="screenrecord_stop_text" msgid="6549288689506057686">"Toque para parar"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
- <string name="screenrecord_pause_label" msgid="6004054907104549857">"Colocar em pausa"</string>
+ <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Partilhar"</string>
@@ -917,7 +917,7 @@
<string name="pip_notification_title" msgid="8661573026059630525">"A app <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string>
<string name="pip_notification_message" msgid="4991831338795022227">"Se não pretende que a app <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string>
<string name="pip_play" msgid="333995977693142810">"Reproduzir"</string>
- <string name="pip_pause" msgid="1139598607050555845">"Colocar em pausa"</string>
+ <string name="pip_pause" msgid="1139598607050555845">"Pausar"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Mudar para o seguinte"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Mudar para o anterior"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telem. deslig. devido ao calor"</string>
@@ -1014,9 +1014,9 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Aceda às Definições para atualizar a navegação no sistema."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Conversa definida como prioritária"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"As conversas com prioridade irão:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecem na parte superior da secção de conversas."</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostram a imagem do perfil no ecrã de bloqueio."</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"As conversas prioritárias irão:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecer na parte superior da secção de conversas."</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrar a imagem do perfil no ecrã de bloqueio."</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecem como balões flutuantes por cima de apps."</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrompem o modo Não incomodar."</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Toque sem soltar e arraste para reorganizar os controlos."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Todos os controlos foram removidos."</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Alterações não guardadas."</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Não foi possível carregar a lista dos controlos."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adicione aos controlos de dispositivos"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 9b3976eaffb8..cd436ddd3cf4 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"A conversa foi definida como prioritária"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"As conversas prioritárias:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecer na parte superior da seção de conversa"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrar foto do perfil na tela de bloqueio"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecem na parte superior da seção de conversa"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostram a foto do perfil na tela de bloqueio"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecer como balões flutuantes sobre outros apps"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interromper o \"Não perturbe\""</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Ok"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Toque no controle, mantenha-o pressionado e arraste para reorganizar as posições."</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Todos os controles foram removidos"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"As mudanças não foram salvas"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Não foi possível carregar a lista de controles."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adicionar aos controles do dispositivo"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0f0f598cebf4..2b154df82644 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1051,7 +1051,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Țineți apăsat și trageți pentru a rearanja comenzile"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Au fost șterse toate comenzile"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Modificările nu au fost salvate"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Lista cu toate comenzile nu a putut fi încărcată."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Comenzile nu au putut fi încărcate. Accesați aplicația <xliff:g id="APP">%s</xliff:g> pentru a vă asigura că setările aplicației nu s-au schimbat."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Nu sunt disponibile comenzi compatibile"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altul"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Adăugați la comenzile dispozitivelor"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Adăugați"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d2bda6e4e259..2ad69d68ebe9 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -419,7 +419,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ограничение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Рабочий профиль"</string>
- <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Ночной режим"</string>
+ <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Ночная подсветка"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Вкл. на закате"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"До рассвета"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -1012,21 +1012,21 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Перенести в правый верхний угол"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Перенести в левый нижний угол"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Перенести в правый нижний угол"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Закрыть всплывающий чат"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не показывать всплывающие чаты для разговоров"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Скрыть всплывающий чат"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не показывать всплывающий чат для разговора"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Всплывающие чаты"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Новые разговоры будут появляться в виде плавающих значков, или всплывающих чатов. Чтобы открыть чат, нажмите на него, а чтобы переместить – перетащите."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Настройки всплывающих чатов"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Чтобы отключить всплывающие чаты от приложения, нажмите \"Настроить\"."</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Всплывающие чаты"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Чтобы отключить всплывающие чаты из этого приложения, нажмите \"Настроить\"."</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"ОК"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: настройки"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Параметры навигации в системе обновлены. Чтобы изменить их, перейдите в настройки."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Чтобы обновить параметры навигации в системе, перейдите в настройки."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Переход в режим ожидания"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Разговор помечен как важный"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Важные разговоры:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Показывать в верхней части списка разговоров"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Показывать фото профиля на заблокированном экране"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Преимущества:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Важные разговоры показываются в верхней части списка разговоров."</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Фото профиля показывается на заблокированном экране."</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Показывать как всплывающий чат над приложениями"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Показывать в режиме \"Не беспокоить\""</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"ОК"</string>
@@ -1034,8 +1034,8 @@
<string name="magnification_overlay_title" msgid="6584179429612427958">"Наложение окна увеличения"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Окно увеличения"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Настройки окна увеличения"</string>
- <string name="quick_controls_title" msgid="6839108006171302273">"Виджеты управления устройствами"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"Добавьте элементы управления для подключенных устройств"</string>
+ <string name="quick_controls_title" msgid="6839108006171302273">"Управление устройствами"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"Добавьте виджеты для управления устройствами."</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Настройте виджеты управления устройствами"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Чтобы перейти к элементам управления, удерживайте кнопку питания."</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Чтобы добавить элементы управления, выберите приложение"</string>
@@ -1057,7 +1057,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Чтобы изменить порядок элементов управления, перетащите их"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Все элементы управления удалены"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Изменения не сохранены."</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Не удалось загрузить список элементов управления."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Другое"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Добавьте виджеты управления устройствами"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Добавить"</string>
@@ -1079,7 +1082,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"Ошибка. Повторная попытка…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не найдено."</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Управление недоступно"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"Нет доступа к устройству (<xliff:g id="DEVICE">%1$s</xliff:g>). Проверьте, доступно ли управление в приложении \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" и не изменились ли настройки этого приложения."</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Нет доступа к устройству \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Проверьте, доступно ли управление в приложении \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" и не изменились ли настройки этого приложения."</string>
<string name="controls_open_app" msgid="483650971094300141">"Открыть приложение"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Не удалось загрузить статус."</string>
<string name="controls_error_failed" msgid="960228639198558525">"Ошибка. Повторите попытку."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index b9b95ac45f81..295e27e1b6f1 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"පාලන නැවත පිළියෙළ කිරීමට අල්ලාගෙන සිට අදින්න"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"සියලු පාලන ඉවත් කර ඇත"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"වෙනස් කිරීම් නොසුරැකිණි"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"සියලු පාලනවල ලැයිස්තුව පූරණය කළ නොහැකි විය."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"පාලන පූරණය කළ නොහැකි විය. යෙදුම් සැකසීම් වෙනස් වී නැති බව සහතික කර ගැනීමට <xliff:g id="APP">%s</xliff:g> යෙදුම පරීක්ෂා කරන්න."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"ගැළපෙන පාලන ලබා ගත නොහැකිය"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"වෙනත්"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"උපාංග පාලන වෙත එක් කරන්න"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"එක් කරන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c776f2e7a3f0..484c6694af9b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1016,17 +1016,17 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nezobrazovať konverzáciu ako bublinu"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Čet pomocou bublín"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nové konverzácie sa zobrazujú ako plávajúce ikony či bubliny. Bublinu otvoríte klepnutím. Premiestnite ju presunutím."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Ovládajte bubliny kedykoľvek"</string>
- <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Klepnutím na Spravovať vypnite bubliny z tejto aplikácie"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Nastavenie bublín môžete kedykoľvek zmeniť"</string>
+ <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Bubliny pre túto aplikáciu môžete vypnúť klepnutím na Spravovať"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Dobre"</string>
- <string name="bubbles_app_settings" msgid="5779443644062348657">"Nastavenia upozornenia <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
+ <string name="bubbles_app_settings" msgid="5779443644062348657">"Nastavenia aplikácie <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigácia v systéme bola aktualizovaná. Ak chcete vykonať zmeny, prejdite do Nastavení."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Prejdite do Nastavení a aktualizujte navigáciu v systéme"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostný režim"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Konverzácia je nastavená ako prioritná"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Správanie prioritných konverzácií:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Zobrazovať hore v sekcii konverzácií"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Zobrazovať profilovú fotku na uzamknutej obrazovke"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prioritné konverzácie:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"sa zobrazujú navrchu sekcie konverzácií"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"zobrazujú profilovú fotku na uzamknutej obrazovke"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Zobrazovať ako plávajúce bubliny nad aplikáciami"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Prerušovať režim bez vyrušení"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Dobre"</string>
@@ -1057,7 +1057,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Polohu každého ovládača môžete zmeniť jeho pridržaním a presunutím"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Všetky ovládače boli odstránené"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Zmeny neboli uložené"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Zoznam všetkých ovl. prvkov sa nepodarilo načítať."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Iné"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Pridanie do ovládania zariadení"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Pridať"</string>
@@ -1078,8 +1081,8 @@
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Chyba, skúša sa znova…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenájdené"</string>
- <string name="controls_error_removed_title" msgid="1207794911208047818">"Ovládanie nie je k dispozícii"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"Nepodarilo sa získať prístup k zariadeniu <xliff:g id="DEVICE">%1$s</xliff:g>. V aplikácii <xliff:g id="APPLICATION">%2$s</xliff:g> skontrolujte, či je ovládanie stále k dispozícii a či sa nezmenili nastavenia."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Ovládač nie je k dispozícii"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nepodarilo sa získať prístup k zariadeniu <xliff:g id="DEVICE">%1$s</xliff:g>. V aplikácii <xliff:g id="APPLICATION">%2$s</xliff:g> skontrolujte, či je ovládač stále k dispozícii a či sa nezmenili nastavenia."</string>
<string name="controls_open_app" msgid="483650971094300141">"Otvoriť aplikáciu"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Stav sa nepodarilo načítať"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Chyba, skúste to znova"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 326ae97cdec3..67f08dbc5fca 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1016,7 +1016,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Pogovora ne prikaži v oblačku"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Klepet z oblački"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Novi pogovori so prikazani kot lebdeče ikone ali oblački. Če želite odpreti oblaček, se ga dotaknite. Če ga želite premakniti, ga povlecite."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Upravljanje oblačkov kadar koli"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Upravljanje oblačkov"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Dotaknite se »Upravljanje«, da izklopite oblačke iz te aplikacije"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Razumem"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Nastavitve za <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1025,8 +1025,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravljenosti"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Pogovor je nastavljen kot prednosten"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Prednostni pogovori bodo:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazano na vrhu razdelka s pogovorom"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikaz profilne slike na zaklenjenem zaslonu"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazani na vrhu razdelka s pogovorom"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazali profilno sliko na zaklenjenem zaslonu"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Prikazano kot lebdeč oblaček čez druge aplikacije"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Preglasi način »ne moti«"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"V redu"</string>
@@ -1057,7 +1057,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Držite in povlecite, da prerazporedite kontrolnike"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Vsi kontrolniki so bili odstranjeni"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Spremembe niso shranjene"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Seznama vseh kontrolnikov ni bilo mogoče naložiti."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kontrolnikov ni bilo mogoče naložiti. Odprite aplikacijo <xliff:g id="APP">%s</xliff:g> in se prepričajte, da se njene nastavitve niso spremenile."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Združljivi kontrolniki niso na voljo"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Dodajanje med kontrolnike naprave"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index d0d16c367b2c..bf1085887d70 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Në gatishmëri"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Biseda u caktua me përparësi"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Bisedat me përparësi do të:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Shfaq në krye të seksionit të bisedës"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Shfaq figurën e profilit në ekranin e kyçjes"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Shfaqen në krye të seksionit të bisedës"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Shfaqin fotografinë e profilit në ekranin e kyçjes"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Shfaq si flluskë pluskuese mbi aplikacione"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ndërprit \"Mos shqetëso\""</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"E kuptova"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mbaje të shtypur dhe zvarrit për të risistemuar kontrollet"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Të gjitha kontrollet u hoqën"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Ndryshimet nuk u ruajtën"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Lista e të gjitha kontrolleve nuk mund të ngarkohej."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Tjetër"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Shto te kontrollet e pajisjes"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Shto"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f692e1cc20d9..ff2da873a8c4 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1007,7 +1007,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Премести горе десно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Премести доле лево"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Премести доле десно"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Одбацивање облачића"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Одбаци облачић"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не користи облачиће за конверзацију"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Ћаскајте у облачићима"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Нове конверзације се приказују као плутајуће иконе или облачићи. Додирните да бисте отворили облачић. Превуците да бисте га преместили."</string>
@@ -1019,9 +1019,9 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Идите у Подешавања да бисте ажурирали навигацију система"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Стање приправности"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Конверзација је подешена на приоритетну"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Приоритетне конверзације ће:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Приказује се у врху одељка за конверзације"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Приказује слику профила на закључаном екрану"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Приоритетне конверзације:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"се приказују у врху одељка за конверзације"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"приказују слику профила на закључаном екрану"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Приказују се плутајући облачићи преко апликација"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Омета подешавање Не узнемиравај"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Важи"</string>
@@ -1051,7 +1051,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Задржите и превуците да бисте променили распоред контрола"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Све контроле су уклоњене"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Промене нису сачуване"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Учитавање листе свих контрола није успело."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Учитавање контрола није успело. Погледајте апликацију <xliff:g id="APP">%s</xliff:g> да бисте се уверили да се подешавања апликације нису променила."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Компатибилне контроле нису доступне"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друго"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Додајте у контроле уређаја"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index f7d19ac3472d..25316d15a261 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Viloläge"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Konversationen har angetts som prioriterad"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Följande gäller för prioriterade konversationer:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Visa högst upp bland konversationerna"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Visa profilbild på låsskärmen"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"De visas högst upp bland konversationerna"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Profilbilden visas på låsskärmen"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Visa som en flytande bubbla ovanpå appar"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Avbryt Stör ej"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Ändra ordning på kontrollerna genom att trycka och dra"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Alla kontroller har tagits bort"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Ändringarna har inte sparats"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Listan med alla kontroller kunde inte läsas in."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Det gick inte att läsa in enhetsstyrning. Kontrollera att inställningarna inte har ändrats i <xliff:g id="APP">%s</xliff:g>-appen."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Ingen kompatibel enhetsstyrning tillgänglig"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Övrigt"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Lägg till i enhetsstyrning"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Lägg till"</string>
@@ -1069,7 +1070,7 @@
<string name="controls_error_removed_title" msgid="1207794911208047818">"Styrning är inte tillgänglig"</string>
<string name="controls_error_removed_message" msgid="2885911717034750542">"Det gick inte att komma åt <xliff:g id="DEVICE">%1$s</xliff:g>. Kontrollera att enheten fortfarande är tillgänglig för styrning och att appinställningarna inte har ändrats i <xliff:g id="APPLICATION">%2$s</xliff:g>-appen."</string>
<string name="controls_open_app" msgid="483650971094300141">"Öppna appen"</string>
- <string name="controls_error_generic" msgid="352500456918362905">"Ingen status lästes in"</string>
+ <string name="controls_error_generic" msgid="352500456918362905">"Status otillgänglig"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Fel, försök igen"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Pågår"</string>
<string name="controls_added_tooltip" msgid="4842812921719153085">"De nya snabbkontrollerna visas om du håller strömbrytaren nedtryckt"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 1a0b9ec653ae..f8bd10c3ab2b 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Hali tuli"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Mazungumzo yamepewa kipaumbele"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Mazungumzo yaliyopewa kipaumbele:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Onyesha kwenye sehemu ya juu ya mazungumzo"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Onyesha picha ya wasifu kwenye skrini iliyofungwa"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Huonyeshwa kwenye sehemu ya juu ya mazungumzo"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Huonyesha picha ya wasifu kwenye skrini iliyofungwa"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Yataonekana kama kiputo kinachoelea juu ya programu"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Katiza kipengele cha Usinisumbue"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Nimeelewa"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Shikilia na uburute ili upange vidhibiti upya"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Umeondoa vidhibiti vyote"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Mabadiliko hayajahifadhiwa"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Imeshindwa kupakia orodha ya vidhibiti vyote."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Imeshindwa kupakia vidhibiti. Angalia programu ya <xliff:g id="APP">%s</xliff:g> ili uhakikishe kuwa mipangilio ya programu haijabadilika."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Vidhibiti vinavyooana havipatikani"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Nyingine"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Weka kwenye vidhibiti vya vifaa"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Weka"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 29a186f481cc..bf30ca956bc4 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"கட்டுப்பாடுகளை மறுவரிசைப்படுத்த அவற்றைப் பிடித்து இழுக்கவும்"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"கட்டுப்பாடுகள் அனைத்தும் அகற்றப்பட்டன"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"மாற்றங்கள் சேமிக்கப்படவில்லை"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"எல்லா கட்டுப்பாடுகளின் பட்டியலை ஏற்ற முடியவில்லை."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"கட்டுப்பாடுகளை ஏற்ற முடியவில்லை. ஆப்ஸ் அமைப்புகள் மாறவில்லை என்பதை உறுதிப்படுத்த <xliff:g id="APP">%s</xliff:g> ஆப்ஸைப் பார்க்கவும்."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"இணக்கமான கட்டுப்பாடுகள் இல்லை"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"பிற"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"சாதனக் கட்டுப்பாடுகளில் சேர்த்தல்"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"சேர்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 4b56e157b34f..de57d2724ab3 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"నియంత్రణల క్రమం మార్చడానికి దేనినైనా పట్టుకుని, లాగి వదిలేయండి"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"అన్ని నియంత్రణలు తీసివేయబడ్డాయి"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"మార్పులు సేవ్ చేయబడలేదు"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"అన్ని నియంత్రణలు గల జాబితాను లోడ్ చేయలేకపోయాము."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"కంట్రోల్‌లను లోడ్ చేయడం సాధ్యపడలేదు. యాప్ సెట్టింగ్‌లు మారలేదని నిర్ధారించడానికి <xliff:g id="APP">%s</xliff:g> యాప్‌ను చెక్ చేయండి."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"అనుకూల కంట్రోల్‌లు అందుబాటులో లేవు"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ఇతరం"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"పరికరం నియంత్రణలకు జోడించడం"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"జోడించండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ba16febe18c3..b5563608e13b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"แตะตัวควบคุมค้างไว้แล้วลากเพื่อจัดเรียงใหม่"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"นำตัวควบคุมทั้งหมดออกแล้ว"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ยังไม่ได้บันทึกการเปลี่ยนแปลง"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"โหลดรายการตัวควบคุมทั้งหมดไม่ได้"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"โหลดตัวควบคุมไม่ได้ ตรวจสอบแอป <xliff:g id="APP">%s</xliff:g> ให้แน่ใจว่าการตั้งค่าของแอปไม่เปลี่ยนแปลง"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"ตัวควบคุมความเข้ากันได้ไม่พร้อมใช้งาน"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"อื่นๆ"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"เพิ่มไปยังระบบควบคุมอุปกรณ์"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"เพิ่ม"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e25e52bdf4ab..45f728841b36 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1015,8 +1015,8 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Naka-standby"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Ginawang priyoridad ang pag-uusap"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Ang mga priyoridad na pag-uusap ay:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Ipakita sa itaas ng seksyon ng pag-uusap"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Ipakita ang larawan sa profile sa lock screen"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Lalabas sa itaas ng seksyon ng pag-uusap"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Magpapakita ng larawan sa profile sa lock screen"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Ipakitang floating bubble sa ibabaw ng mga app"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ihinto ang Huwag Istorbohin"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
@@ -1025,7 +1025,7 @@
<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="quick_controls_title" msgid="6839108006171302273">"Mga kontrol ng device"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"Magdagdag ng mga kontrol para sa iyong mga nakakonektang device"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"Magdagdag ng kontrol para sa mga nakakonektang device"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"I-set up ang mga kontrol ng device"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Pindutin nang matagal ang Power button para ma-access ang iyong mga kontrol"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Pumili ng app para magdagdag ng mga kontrol"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"I-hold at i-drag para baguhin ang pagkakaayos ng mga kontrol"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Inalis ang lahat ng kontrol"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Hindi na-save ang mga pagbabago"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Hindi ma-load ang listahan ng lahat ng control."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Hindi ma-load ang mga kontrol. Tingnan ang app na <xliff:g id="APP">%s</xliff:g> para matiyak na hindi nabago ang mga setting ng app."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Hindi available ang mga compatible na kontrol"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Iba pa"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Idagdag sa mga kontrol ng device"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Idagdag"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 6c6b5bf47b3b..88869cd408f9 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Kontrolleri yeniden düzenlemek için basılı tutup sürükleyin"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Tüm kontroller kaldırıldı"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Değişiklikler kaydedilmedi"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Tüm kontrollerin listesi yüklenemedi."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Diğer"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Cihaz denetimlerine ekle"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ekle"</string>
@@ -1067,7 +1070,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"Hata, yeniden deneniyor…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrol kullanılamıyor"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazına erişilemedi Kontrolün hâlâ kullanılabilir olduğundan ve uygulama ayarlarının değişmediğinden emin olmak için <xliff:g id="APPLICATION">%2$s</xliff:g> uygulamasını kontrol edin."</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazına erişilemedi. Kontrolün kullanılabilir olduğundan ve uygulama ayarlarının değişmediğinden emin olmak için <xliff:g id="APPLICATION">%2$s</xliff:g> uygulamasını kontrol edin."</string>
<string name="controls_open_app" msgid="483650971094300141">"Uygulama aç"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Durum yüklenemiyor"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Hata, yeniden deneyin"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index e192c120922f..a401e553a0da 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1016,7 +1016,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не показувати спливаючі чати для розмов"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Спливаючий чат"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Нові повідомлення чату з\'являються у вигляді спливаючих значків. Щоб відкрити чат, натисніть його, а щоб перемістити – перетягніть."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Налаштовуйте спливаючі чати будь-коли"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Контроль спливаючих чатів"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Натисніть \"Налаштувати\", щоб вимкнути спливаючі чати від цього додатка"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Налаштування параметра \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\""</string>
@@ -1057,7 +1057,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Щоб змінити порядок елементів керування, перетягуйте їх"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Усі елементи керування вилучено"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Зміни не збережено"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Не вдалося завантажити список усіх елементів керування."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Інше"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Додати до елементів керування пристроями"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Додати"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d382f4237c47..d72bd92015a3 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1003,7 +1003,7 @@
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"نیچے بائیں جانب لے جائیں"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"نیچے دائیں جانب لے جائیں"</string>
<string name="bubble_dismiss_text" msgid="1314082410868930066">"بلبلہ برخاست کریں"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"بلبلہ گفتگو نہ کریں"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"گفتگو بلبلہ نہ کریں"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"بلبلے کے ذریعے چیٹ کریں"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"نئی گفتگوئیں فلوٹنگ آئیکن یا بلبلے کے طور پر ظاہر ہوں گی۔ بلبلہ کھولنے کے لیے تھپتھپائیں۔ اسے منتقل کرنے کے لیے گھسیٹیں۔"</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"کسی بھی وقت بلبلے کو کنٹرول کریں"</string>
@@ -1014,9 +1014,9 @@
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"سسٹم نیویگیشن اپ ڈیٹ کرنے کے لیے ترتیبات پر جائیں"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"اسٹینڈ بائی"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"گفتگو کو ترجیح پر سیٹ کیا گیا"</string>
- <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ترجیحی گفتگوئیں یہ ہوگی:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"گفتگو کے سیکشن میں سب سے اوپر دکھائیں"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"مقفل سکرین پر پروفائل کی تصویر دکھائیں"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ترجیحی گفتگوئیں:"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"گفتگو سیکشن میں سب سے اوپر نظر آئیں گی"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"مقفل سکرین پر پروفائل کی تصویر دکھائیں گی"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ایپس کے سب سے اوپر فلوٹنگ بلبلہ کے طور پر ظاہر ہوں"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"ڈسٹرب نہ کریں میں مداخلت کریں"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"سمجھ آ گئی"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"کنٹرولز کو دوبارہ ترتیب دینے کے ليے پکڑیں اور گھسیٹیں"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"سبھی کنٹرولز ہٹا دیے گئے"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"تبدیلیاں محفوظ نہیں ہوئیں"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"تمام کنٹرولز کی فہرست لوڈ نہیں کی جا سکی۔"</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"دیگر"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"آلہ کے کنٹرولز میں شامل کریں"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"شامل کریں"</string>
@@ -1067,7 +1070,7 @@
<string name="controls_error_retryable" msgid="864025882878378470">"خرابی، دوبارہ کوشش کی جا رہی ہے…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"نہیں ملا"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"کنٹرول دستیاب نہیں ہے"</string>
- <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> تک رسائی حاصل نہیں ہو سکی۔ اس بات کو یقینی بنانے کے لیے کہ کنٹرول ابھی بھی دستیاب ہے اور ایپ کی ترتیبات تبدیل نہیں ہوئی، تو <xliff:g id="APPLICATION">%2$s</xliff:g> ایپ چیک کریں۔"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"‫<xliff:g id="DEVICE">%1$s</xliff:g> تک رسائی حاصل نہیں ہو سکی۔ اس بات کو یقینی بنانے کے لیے کہ کنٹرول ابھی بھی دستیاب ہے اور ایپ کی ترتیبات تبدیل نہیں ہوئی، تو <xliff:g id="APPLICATION">%2$s</xliff:g> ایپ چیک کریں۔"</string>
<string name="controls_open_app" msgid="483650971094300141">"ایپ کھولیں"</string>
<string name="controls_error_generic" msgid="352500456918362905">"صورتحال لوڈ نہیں ہو سکتی"</string>
<string name="controls_error_failed" msgid="960228639198558525">"خرابی، دوبارہ کوشش کریں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 3099270c0d80..4ada3a52302d 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1002,11 +1002,11 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Yuqori oʻngga surish"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Quyi chapga surish"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Quyi oʻngga surish"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"Pufakni yopish"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Bulutchani yopish"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Suhbatlar bulutchalar shaklida chiqmasin"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Bulutchalar yordamida subhatlashish"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Yangi xabarlar qalqib chiquvchi belgilar yoki bulutchalar kabi chiqadi. Xabarni ochish uchun bildirishnoma ustiga bosing. Xabarni qayta joylash uchun bildirishnomani suring."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Bulutcha shaklidagi bildirishnomalarni sozlash"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Bulutchalardagi bildirishnomalar"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Bu ilova bulutchalarini faolsizlantirish uchun Boshqarish tugmasini bosing"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> sozlamalari"</string>
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Boshqaruv elementlarini qayta tartiblash uchun ushlab torting"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Barcha boshqaruv elementlari olib tashlandi"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Oʻzgarishlar saqlanmadi"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Boshqaruv elementlarining barchasi yuklanmadi."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Boshqa"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Qurilma boshqaruv elementlariga kiritish"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Kiritish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index cc6a8fd25826..4a592840ac6f 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -686,7 +686,7 @@
<string name="do_not_silence_block" msgid="4361847809775811849">"Không im lặng hoặc chặn"</string>
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"Điều khiển thông báo nguồn"</string>
<string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Bật"</string>
- <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Tắt"</string>
+ <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Đang tắt"</string>
<string name="power_notification_controls_description" msgid="1334963837572708952">"Với các kiểm soát thông báo nguồn, bạn có thể đặt cấp độ quan trọng từ 0 đến 5 cho các thông báo của ứng dụng. \n\n"<b>"Cấp 5"</b>" \n- Hiển thị ở đầu danh sách thông báo \n- Cho phép gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 4"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 3"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n\n"<b>"Cấp 2"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n\n"<b>"Cấp 1"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n- Ẩn khỏi màn hình khóa và thanh trạng thái \n- Hiển thị ở cuối danh sách thông báo \n\n"<b>"Cấp 0"</b>" \n- Chặn tất cả các thông báo từ ứng dụng"</string>
<string name="notification_header_default_channel" msgid="225454696914642444">"Thông báo"</string>
<string name="notification_channel_disabled" msgid="928065923928416337">"Bạn sẽ không thấy các thông báo này nữa"</string>
@@ -1006,7 +1006,7 @@
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Dừng trò chuyện bằng bong bóng"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Trò chuyện bằng bong bóng trò chuyện"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Các cuộc trò chuyện mới sẽ xuất hiện dưới dạng biểu tượng nổi hoặc bong bóng trò chuyện. Nhấn để mở bong bóng trò chuyện. Kéo để di chuyển bong bóng trò chuyện."</string>
- <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Kiểm soát tùy chọn cài đặt bong bóng trò chuyện bất mọi lúc"</string>
+ <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Kiểm soát bong bóng bất cứ lúc nào"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Nhấn vào nút Quản lý để tắt bong bóng trò chuyện từ ứng dụng này"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
<string name="bubbles_app_settings" msgid="5779443644062348657">"Cài đặt <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Giữ và kéo để sắp xếp lại các tùy chọn điều khiển"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Đã xóa tất cả tùy chọn điều khiển"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Chưa lưu các thay đổi"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Không thể tải danh sách tất cả tùy chọn điều khiển."</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"Không tải được các chức năng điều khiển. Hãy kiểm tra ứng dụng <xliff:g id="APP">%s</xliff:g> để đảm bảo rằng thông tin cài đặt của ứng dụng chưa thay đổi."</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"Không có các chức năng điều khiển tương thích"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Khác"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Thêm vào mục điều khiển thiết bị"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Thêm"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 73fac041f446..2b500affd209 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住并拖动即可重新排列控件"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"已移除所有控件"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"未保存更改"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"无法加载所有控件的列表。"</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"添加到设备控件"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"添加"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 5f5c85fcc8ef..59867b7679ef 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -593,12 +593,12 @@
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string>
<string name="accessibility_output_chooser" msgid="7807898688967194183">"切換輸出裝置"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"已固定應用程式"</string>
- <string name="screen_pinning_description" msgid="8699395373875667743">"畫面將會繼續顯示,直至您取消固定。按住 [返回] 和 [概覽] 即可取消固定。"</string>
- <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"畫面將會繼續顯示,直至您取消固定為止。按住 [返回] 按鈕和主按鈕即可取消固定。"</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"畫面將會繼續顯示,直至您取消固定為止。向上滑動並按住即可取消固定。"</string>
- <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"畫面將會繼續顯示,直至您取消固定。按住 [概覽] 即可取消固定。"</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"畫面將會繼續顯示,直至您取消固定為止。按住主按鈕即可取消固定。"</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"該應用程式可存取個人資料 (例如聯絡人和電郵內容)。"</string>
+ <string name="screen_pinning_description" msgid="8699395373875667743">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。按住「返回」和「概覽」按鈕即可取消固定。"</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。按住「返回」按鈕和主按鈕即可取消固定。"</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。向上滑動後按住即可取消固定。"</string>
+ <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。按住「概覽」按鈕即可取消固定。"</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。按住主按鈕即可取消固定。"</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"應用程式可能會存取個人資料 (例如通訊錄和電郵內容)。"</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"固定的應用程式可開啟其他應用程式。"</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"如要取消固定此應用程式,請按住「返回」按鈕和「概覽」按鈕"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"如要取消固定此應用程式,請按住「返回」按鈕和主按鈕"</string>
@@ -1002,7 +1002,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"移去右上角"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"移去左下角"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"移去右下角"</string>
- <string name="bubble_dismiss_text" msgid="1314082410868930066">"關閉對話氣泡"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"關閉小視窗氣泡"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"不要透過小視窗顯示對話"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"使用小視窗進行即時通訊"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"新對話會以浮動圖示 (小視窗) 顯示。輕按即可開啟小視窗。拖曳即可移動小視窗。"</string>
@@ -1025,7 +1025,7 @@
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"裝置控制"</string>
- <string name="quick_controls_subtitle" msgid="1667408093326318053">"為已連接的裝置新增控制項"</string>
+ <string name="quick_controls_subtitle" msgid="1667408093326318053">"為連接的裝置新增控制選項"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"設定裝置控制"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"按住「開關」按鈕便可存取控制項"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"選擇要新增控制項的應用程式"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住並拖曳便可重新排列控制項"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"已移除所有控制項"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"未儲存變更"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"無法載入完整控制項清單。"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"無法載入控制項。請檢查 <xliff:g id="APP">%s</xliff:g> 應用程式,確定應用程式設定並無變更。"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"沒有可用的兼容控制項"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"加到裝置控制"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
@@ -1070,7 +1071,7 @@
<string name="controls_error_removed_message" msgid="2885911717034750542">"無法存取 <xliff:g id="DEVICE">%1$s</xliff:g>。請檢查 <xliff:g id="APPLICATION">%2$s</xliff:g> 應用程式,確定控制功能仍可使用,同時應用程式設定並無變更。"</string>
<string name="controls_open_app" msgid="483650971094300141">"開啟應用程式"</string>
<string name="controls_error_generic" msgid="352500456918362905">"無法載入狀態"</string>
- <string name="controls_error_failed" msgid="960228639198558525">"發生錯誤,請再試一次"</string>
+ <string name="controls_error_failed" msgid="960228639198558525">"發生錯誤,請重試"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"進行中"</string>
<string name="controls_added_tooltip" msgid="4842812921719153085">"按住「開關」按鈕以查看新控制項"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 9847871c2efc..01a8c5d2ec7b 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1013,7 +1013,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系統操作機制已更新。如要進行變更,請前往「設定」。"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"請前往「設定」更新系統操作機制"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待機"</string>
- <string name="priority_onboarding_title" msgid="2893070698479227616">"將對話設為優先"</string>
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"對話已設為優先"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"優先對話會:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"顯示在對話部分的頂端"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"在螢幕鎖定畫面上顯示個人資料相片"</string>
@@ -1045,7 +1045,8 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住並拖曳即可重新排列控制項"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"所有控制項都已移除"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"未儲存變更"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"無法載入完整的控制項清單。"</string>
+ <string name="controls_favorite_load_error" msgid="5126216176144877419">"無法載入控制項。請查看「<xliff:g id="APP">%s</xliff:g>」應用程式,確認應用程式設定沒有任何異動。"</string>
+ <string name="controls_favorite_load_none" msgid="7687593026725357775">"找不到相容的控制項"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"新增至裝置控制"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 9b76660e6cd3..4e68694fcb13 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1045,7 +1045,10 @@
<string name="controls_favorite_rearrange" msgid="5616952398043063519">"Bamba futhi uhudule ukuze uphinde ulungise izilawuli"</string>
<string name="controls_favorite_removed" msgid="5276978408529217272">"Zonke izilawuli zisusiwe"</string>
<string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Izinguquko azilondolozwanga"</string>
- <string name="controls_favorite_load_error" msgid="2533215155804455348">"Uhlu lwazo zonke izilawuli alilayishekanga."</string>
+ <!-- no translation found for controls_favorite_load_error (5126216176144877419) -->
+ <skip />
+ <!-- no translation found for controls_favorite_load_none (7687593026725357775) -->
+ <skip />
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Okunye"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Engeza kuzilawuli zezinsiza"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Engeza"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9bcfdc43fbbf..c06b9161ad1f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1058,6 +1058,10 @@
<!-- Shift quick access wallet down in Global Actions when Controls are unavailable -->
<dimen name="global_actions_wallet_top_margin">40dp</dimen>
+ <!-- Shutdown and restart actions are larger in power options dialog -->
+ <dimen name="global_actions_power_dialog_item_height">190dp</dimen>
+ <dimen name="global_actions_power_dialog_item_width">255dp</dimen>
+
<!-- The maximum offset in either direction that elements are moved horizontally to prevent
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_x">8dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index d47ad7fcdfbd..8212d6159737 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -174,5 +174,8 @@
<item type="id" name="accessibility_action_controls_move_before" />
<item type="id" name="accessibility_action_controls_move_after" />
+
+ <!-- Accessibility actions for PIP -->
+ <item type="id" name="action_pip_resize" />
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 73568eab5eac..ebbf8f298944 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1091,11 +1091,11 @@
<!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] -->
<string name="keyguard_retry">Swipe up to try again</string>
- <!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
- <string name="do_disclosure_generic">This device is managed by your organization</string>
+ <!-- Text on keyguard screen and in Quick Settings footer indicating that the user's device belongs to their organization. [CHAR LIMIT=60] -->
+ <string name="do_disclosure_generic">This device belongs to your organization</string>
- <!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=40] -->
- <string name="do_disclosure_with_name">This device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g></string>
+ <!-- Text on keyguard screen and in Quick Settings footer indicating that user's device belongs to their organization. [CHAR LIMIT=40] -->
+ <string name="do_disclosure_with_name">This device belongs to <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g></string>
<!-- Shows when people have clicked on the phone icon [CHAR LIMIT=60] -->
<string name="phone_hint">Swipe from icon for phone</string>
@@ -1288,29 +1288,29 @@
<!-- Footer vpn present text [CHAR LIMIT=50] -->
<string name="branded_vpn_footer">Network may be monitored</string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner that can monitor the network traffic [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_management_monitoring">Your organization manages this device and may monitor network traffic</string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization, and the organization can monitor network traffic on that device. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_management_monitoring">Your organization owns this device and may monitor network traffic</string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner that can monitor the network traffic [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_named_management_monitoring"><xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> manages this device and may monitor network traffic</string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization, and the organization can monitor network traffic on that device. The placeholder is the organization's name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_named_management_monitoring"><xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> owns this device and may monitor network traffic</string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner and is connected to a VPN [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_management_named_vpn">Device is managed by your organization and connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization, and the device is connected to a VPN. The placeholder is the VPN name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_management_named_vpn">This device belongs to your organization and is connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner and is connected to a VPN [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_named_management_named_vpn">Device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> and connected to <xliff:g id="vpn_app" example="Foo VPN App">%2$s</xliff:g></string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization, and the device is connected to a VPN. The first placeholder is the organization name, and the second placeholder is the VPN name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_named_management_named_vpn">This device belongs to <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> and is connected to <xliff:g id="vpn_app" example="Foo VPN App">%2$s</xliff:g></string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_management">Device is managed by your organization</string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_management">This device belongs to your organization</string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_named_management">Device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g></string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization. The placeholder is the organization's name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_named_management">This device belongs to <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g></string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner and is connected to two VPNs, one in the current user, one in the managed profile [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_management_vpns">Device is managed by your organization and connected to VPNs</string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization, and the device is connected to multiple VPNs. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_management_vpns">This device belongs to your organization and is connected to VPNs</string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device has a device owner and is connected to two VPNs, one in the current user, one in the managed profile [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_named_management_vpns">Device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> and connected to VPNs</string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the user's device belongs to their organization, and the device is connected to multiple VPNs. The placeholder is the organization's name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_named_management_vpns">This device belongs to <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> and is connected to VPNs</string>
<!-- Disclosure at the bottom of Quick Settings that indicates that the device has a managed profile which can be monitored by the profile owner [CHAR LIMIT=100] -->
<string name="quick_settings_disclosure_managed_profile_monitoring">Your organization may monitor network traffic in your work profile</string>
@@ -1321,17 +1321,17 @@
<!-- Disclosure at the bottom of Quick Settings that indicates that a certificate authorithy is installed on this device and the traffic might be monitored [CHAR LIMIT=100] -->
<string name="quick_settings_disclosure_monitoring">Network may be monitored</string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to two VPNs, one in the current user, one in the managed profile [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_vpns">Device connected to VPNs</string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to multiple VPNs. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_vpns">This device is connected to VPNs</string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to a VPN in the work profile [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_managed_profile_named_vpn">Work profile connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to a VPN in the work profile. The placeholder is the VPN name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_managed_profile_named_vpn">Your work profile is connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to a VPN in the personal profile (as opposed to the work profile) [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_personal_profile_named_vpn">Personal profile connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to a VPN in the personal profile (instead of the work profile). The placeholder is the VPN name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_personal_profile_named_vpn">Your personal profile is connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
- <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to a VPN [CHAR LIMIT=100] -->
- <string name="quick_settings_disclosure_named_vpn">Device connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
+ <!-- Disclosure at the bottom of Quick Settings that indicates that the device is connected to a VPN. The placeholder is the VPN name. [CHAR LIMIT=100] -->
+ <string name="quick_settings_disclosure_named_vpn">This device is connected to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
<!-- Monitoring dialog title for device owned devices [CHAR LIMIT=35] -->
<string name="monitoring_title_device_owned">Device management</string>
@@ -1361,11 +1361,11 @@
<!-- Monitoring dialog label for button opening a page with more information on the admin's abilities [CHAR LIMIT=30] -->
<string name="monitoring_button_view_policies">View Policies</string>
- <!-- Monitoring dialog: Description of the device owner by name. [CHAR LIMIT=NONE]-->
- <string name="monitoring_description_named_management">Your device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g>.\n\nYour admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your admin.</string>
+ <!-- Dialog that a user can access via Quick Settings. The dialog describes what the IT admin can monitor (and the changes they can make) on the user's device. [CHAR LIMIT=NONE]-->
+ <string name="monitoring_description_named_management">This device belongs to <xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin.</string>
- <!-- Monitoring dialog: Description of a device owner. [CHAR LIMIT=NONE]-->
- <string name="monitoring_description_management">Your device is managed by your organization.\n\nYour admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your admin.</string>
+ <!-- Dialog that a user can access via Quick Settings. The dialog describes what the IT admin can monitor (and the changes they can make) on the user's device. [CHAR LIMIT=NONE]-->
+ <string name="monitoring_description_management">This device belongs to your organization.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin.</string>
<!-- Monitoring dialog: Description of a CA Certificate. [CHAR LIMIT=NONE]-->
<string name="monitoring_description_management_ca_certificate">Your organization installed a certificate authority on this device. Your secure network traffic may be monitored or modified.</string>
@@ -2392,6 +2392,9 @@
<!-- Button to skip to the prev media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
<string name="pip_skip_to_prev">Skip to previous</string>
+ <!-- Accessibility action for resizing PIP [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_pip_resize">Resize</string>
+
<!-- Tuner string -->
<string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
<!-- Tuner string -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index eca6ebf7f8e5..279a200949a5 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -18,12 +18,17 @@ package com.android.systemui.shared.recents.model;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
+import static android.graphics.Bitmap.Config.ARGB_8888;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.GraphicBuffer;
import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.util.Log;
/**
* Data for a single thumbnail.
@@ -57,7 +62,15 @@ public class ThumbnailData {
}
public ThumbnailData(TaskSnapshot snapshot) {
- thumbnail = Bitmap.wrapHardwareBuffer(snapshot.getSnapshot(), snapshot.getColorSpace());
+ final GraphicBuffer buffer = snapshot.getSnapshot();
+ if (buffer != null && (buffer.getUsage() & HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE) == 0) {
+ // TODO(b/157562905): Workaround for a crash when we get a snapshot without this state
+ Log.e("ThumbnailData", "Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE");
+ thumbnail = Bitmap.createBitmap(buffer.getWidth(), buffer.getHeight(), ARGB_8888);
+ thumbnail.eraseColor(Color.BLACK);
+ } else {
+ thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.getColorSpace());
+ }
insets = new Rect(snapshot.getContentInsets());
orientation = snapshot.getOrientation();
rotation = snapshot.getRotation();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
index 31fe22e57084..82e6251a4484 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
@@ -115,7 +115,6 @@ public class SyncRtSurfaceTransactionApplierCompat {
t.deferTransactionUntil(surfaceParams.surface, mBarrierSurfaceControl, frame);
surfaceParams.applyTo(t);
}
- t.setEarlyWakeup();
t.apply();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
index bdb6c063521f..b966f9356849 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -99,8 +99,8 @@ public class TransactionCompat {
return this;
}
+ @Deprecated
public TransactionCompat setEarlyWakeup() {
- mTransaction.setEarlyWakeup();
return this;
}
@@ -114,7 +114,7 @@ public class TransactionCompat {
t.deferTransactionUntil(surfaceControl, barrier, frameNumber);
}
+ @Deprecated
public static void setEarlyWakeup(Transaction t) {
- t.setEarlyWakeup();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 7914d864da0f..ee31706c0b94 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -79,7 +79,6 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
-import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -1075,17 +1074,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
!= LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
}
- private boolean isUserEncryptedOrLockdown(int userId) {
- // Biometrics should not be started in this case. Think carefully before modifying this
- // method, see b/79776455
- final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(userId);
- final boolean isLockDown =
- containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
- || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- final boolean isEncrypted = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT);
- return isLockDown || isEncrypted;
- }
-
private boolean containsFlag(int haystack, int needle) {
return (haystack & needle) != 0;
}
@@ -1915,7 +1903,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private boolean shouldListenForFingerprint() {
final boolean allowedOnBouncer =
!(mFingerprintLockedOut && mBouncer && mCredentialAttempted);
- final int user = getCurrentUser();
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
@@ -1924,7 +1911,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
&& !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
&& (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser
- && allowedOnBouncer && !isUserEncryptedOrLockdown(user);
+ && allowedOnBouncer;
return shouldListen;
}
@@ -1938,8 +1925,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& !statusBarShadeLocked;
final int user = getCurrentUser();
final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
- final boolean isTimedOut =
- containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
+ final boolean isLockDown =
+ containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
+ || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+ final boolean isEncryptedOrTimedOut =
+ containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
+ || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
boolean canBypass = mKeyguardBypassController != null
&& mKeyguardBypassController.canBypass();
@@ -1948,9 +1939,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// TrustAgents or biometrics are keeping the device unlocked.
boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass;
- // Scan even when timeout to show a preemptive bouncer when bypassing.
+ // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing.
// Lock-down mode shouldn't scan, since it is more explicit.
- boolean strongAuthAllowsScanning = (!isTimedOut || canBypass && !mBouncer);
+ boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass && !mBouncer)
+ && !isLockDown;
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
@@ -1960,7 +1952,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
&& !mKeyguardGoingAway && mFaceSettingEnabledForUser.get(user) && !mLockIconPressed
&& strongAuthAllowsScanning && mIsPrimaryUser
- && !mSecureCameraLaunched && !isUserEncryptedOrLockdown(user);
+ && !mSecureCameraLaunched;
// Aggregate relevant fields for debug logging.
if (DEBUG_FACE || DEBUG_SPEW) {
@@ -2033,11 +2025,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}
-
- if (isUserEncryptedOrLockdown(userId)) {
- // If this happens, shouldListenForFingerprint() is wrong. SafetyNet for b/79776455
- EventLog.writeEvent(0x534e4554, "79776455", "startListeningForFingerprint");
- }
mFingerprintCancelSignal = new CancellationSignal();
mFpm.authenticate(null, mFingerprintCancelSignal, 0, mFingerprintAuthenticationCallback,
null, userId);
@@ -2056,11 +2043,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (mFaceCancelSignal != null) {
mFaceCancelSignal.cancel();
}
-
- if (isUserEncryptedOrLockdown(userId)) {
- // If this happens, shouldListenForFace() is wrong. SafetyNet for b/79776455
- EventLog.writeEvent(0x534e4554, "79776455", "startListeningForFace");
- }
mFaceCancelSignal = new CancellationSignal();
mFaceManager.authenticate(null, mFaceCancelSignal, 0,
mFaceAuthenticationCallback, null, userId);
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index 82e665bdf5ac..2deeb1230f09 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -29,6 +29,8 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.util.Assert;
+import java.util.Set;
+
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -62,7 +64,7 @@ public class ForegroundServiceController {
/**
* @return true if this user has services missing notifications and therefore needs a
- * disclosure notification.
+ * disclosure notification for running a foreground service.
*/
public boolean isDisclosureNeededForUser(int userId) {
synchronized (mMutex) {
@@ -74,26 +76,26 @@ public class ForegroundServiceController {
/**
* @return true if this user/pkg has a missing or custom layout notification and therefore needs
- * a disclosure notification for system alert windows.
+ * a disclosure notification showing the user which appsOps the app is using.
*/
public boolean isSystemAlertWarningNeeded(int userId, String pkg) {
synchronized (mMutex) {
final ForegroundServicesUserState services = mUserServices.get(userId);
if (services == null) return false;
- return services.getStandardLayoutKey(pkg) == null;
+ return services.getStandardLayoutKeys(pkg) == null;
}
}
/**
- * Returns the key of the foreground service from this package using the standard template,
- * if one exists.
+ * Returns the keys for notifications from this package using the standard template,
+ * if they exist.
*/
@Nullable
- public String getStandardLayoutKey(int userId, String pkg) {
+ public ArraySet<String> getStandardLayoutKeys(int userId, String pkg) {
synchronized (mMutex) {
final ForegroundServicesUserState services = mUserServices.get(userId);
if (services == null) return null;
- return services.getStandardLayoutKey(pkg);
+ return services.getStandardLayoutKeys(pkg);
}
}
@@ -140,25 +142,27 @@ public class ForegroundServiceController {
}
// TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
- // ForegroundCoordinator
- // Update appOp if there's an associated pending or visible notification:
- final String foregroundKey = getStandardLayoutKey(userId, packageName);
- if (foregroundKey != null) {
- final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(foregroundKey);
- if (entry != null
- && uid == entry.getSbn().getUid()
- && packageName.equals(entry.getSbn().getPackageName())) {
- boolean changed;
- synchronized (entry.mActiveAppOps) {
- if (active) {
- changed = entry.mActiveAppOps.add(appOpCode);
- } else {
- changed = entry.mActiveAppOps.remove(appOpCode);
+ // AppOpsCoordinator
+ // Update appOps if there are associated pending or visible notifications
+ final Set<String> notificationKeys = getStandardLayoutKeys(userId, packageName);
+ if (notificationKeys != null) {
+ boolean changed = false;
+ for (String key : notificationKeys) {
+ final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(key);
+ if (entry != null
+ && uid == entry.getSbn().getUid()
+ && packageName.equals(entry.getSbn().getPackageName())) {
+ synchronized (entry.mActiveAppOps) {
+ if (active) {
+ changed |= entry.mActiveAppOps.add(appOpCode);
+ } else {
+ changed |= entry.mActiveAppOps.remove(appOpCode);
+ }
}
}
- if (changed) {
- mEntryManager.updateNotifications("appOpChanged pkg=" + packageName);
- }
+ }
+ if (changed) {
+ mEntryManager.updateNotifications("appOpChanged pkg=" + packageName);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index 650b9a7f9c0c..bb445832da93 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -163,31 +163,31 @@ public class ForegroundServiceNotificationListener {
userState.addImportantNotification(sbn.getPackageName(),
sbn.getKey());
}
- final Notification.Builder builder =
- Notification.Builder.recoverBuilder(
- mContext, sbn.getNotification());
- if (builder.usesStandardHeader()) {
- userState.addStandardLayoutNotification(
- sbn.getPackageName(), sbn.getKey());
- }
+ }
+ final Notification.Builder builder =
+ Notification.Builder.recoverBuilder(
+ mContext, sbn.getNotification());
+ if (builder.usesStandardHeader()) {
+ userState.addStandardLayoutNotification(
+ sbn.getPackageName(), sbn.getKey());
}
}
- tagForeground(entry);
+ tagAppOps(entry);
return true;
},
true /* create if not found */);
}
// TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
- // ForegroundCoordinator
- private void tagForeground(NotificationEntry entry) {
+ // AppOpsCoordinator
+ private void tagAppOps(NotificationEntry entry) {
final StatusBarNotification sbn = entry.getSbn();
ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
sbn.getUserId(),
sbn.getPackageName());
- if (activeOps != null) {
- synchronized (entry.mActiveAppOps) {
- entry.mActiveAppOps.clear();
+ synchronized (entry.mActiveAppOps) {
+ entry.mActiveAppOps.clear();
+ if (activeOps != null) {
entry.mActiveAppOps.addAll(activeOps);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
index 2ef46dca317a..5c2950f1365d 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
@@ -30,9 +30,11 @@ public class ForegroundServicesUserState {
private String[] mRunning = null;
private long mServiceStartTime = 0;
- // package -> sufficiently important posted notification keys
+
+ // package -> sufficiently important posted notification keys that signal an app is
+ // running a foreground service
private ArrayMap<String, ArraySet<String>> mImportantNotifications = new ArrayMap<>(1);
- // package -> standard layout posted notification keys
+ // package -> standard layout posted notification keys that can display appOps
private ArrayMap<String, ArraySet<String>> mStandardLayoutNotifications = new ArrayMap<>(1);
// package -> app ops
@@ -110,6 +112,11 @@ public class ForegroundServicesUserState {
return found;
}
+ /**
+ * System disclosures for foreground services are required if an app has a foreground service
+ * running AND the app hasn't posted its own notification signalling it is running a
+ * foreground service
+ */
public boolean isDisclosureNeeded() {
if (mRunning != null
&& System.currentTimeMillis() - mServiceStartTime
@@ -129,12 +136,15 @@ public class ForegroundServicesUserState {
return mAppOps.get(pkg);
}
- public String getStandardLayoutKey(String pkg) {
+ /**
+ * Gets the notifications with standard layouts associated with this package
+ */
+ public ArraySet<String> getStandardLayoutKeys(String pkg) {
final ArraySet<String> set = mStandardLayoutNotifications.get(pkg);
if (set == null || set.size() == 0) {
return null;
}
- return set.valueAt(0);
+ return set;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt b/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt
index e65139275685..08edad3a7f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt
@@ -63,7 +63,7 @@ open class AssistLogger @Inject constructor(
}
fun reportAssistantInvocationEvent(
- invocationEvent: AssistantInvocationEvent,
+ invocationEvent: UiEventLogger.UiEventEnum,
assistantComponent: ComponentName? = null,
deviceState: Int? = null
) {
@@ -86,7 +86,7 @@ open class AssistLogger @Inject constructor(
reportAssistantInvocationExtraData()
}
- fun reportAssistantSessionEvent(sessionEvent: AssistantSessionEvent) {
+ fun reportAssistantSessionEvent(sessionEvent: UiEventLogger.UiEventEnum) {
val assistantComponent = getAssistantComponentForCurrentUser()
val assistantUid = getAssistantUid(assistantComponent)
uiEventLogger.logWithInstanceId(
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt b/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt
new file mode 100644
index 000000000000..434b03d404dc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.broadcast
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.util.ArraySet
+import com.android.systemui.Dumpable
+import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
+import com.android.systemui.util.indentIfPossible
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import java.util.concurrent.Executor
+import java.util.concurrent.atomic.AtomicInteger
+
+/**
+ * Receiver for a given action-userId pair to be used by [UserBroadcastDispatcher].
+ *
+ * Each object of this class will take care of a single Action. It will register if it has at least
+ * one [BroadcastReceiver] added to it, and unregister when none are left.
+ *
+ * It will also re-register if filters with new categories are added. But this should not happen
+ * often.
+ *
+ * This class has no sync controls, so make sure to only make modifications from the background
+ * thread.
+ */
+class ActionReceiver(
+ private val action: String,
+ private val userId: Int,
+ private val registerAction: BroadcastReceiver.(IntentFilter) -> Unit,
+ private val unregisterAction: BroadcastReceiver.() -> Unit,
+ private val bgExecutor: Executor,
+ private val logger: BroadcastDispatcherLogger
+) : BroadcastReceiver(), Dumpable {
+
+ companion object {
+ val index = AtomicInteger(0)
+ }
+
+ var registered = false
+ private set
+ private val receiverDatas = ArraySet<ReceiverData>()
+ private val activeCategories = ArraySet<String>()
+
+ @Throws(IllegalArgumentException::class)
+ fun addReceiverData(receiverData: ReceiverData) {
+ if (!receiverData.filter.hasAction(action)) {
+ throw(IllegalArgumentException("Trying to attach to $action without correct action," +
+ "receiver: ${receiverData.receiver}"))
+ }
+ val addedCategories = activeCategories
+ .addAll(receiverData.filter.categoriesIterator()?.asSequence() ?: emptySequence())
+
+ if (receiverDatas.add(receiverData) && receiverDatas.size == 1) {
+ registerAction(createFilter())
+ registered = true
+ } else if (addedCategories) {
+ unregisterAction()
+ registerAction(createFilter())
+ }
+ }
+
+ fun hasReceiver(receiver: BroadcastReceiver): Boolean {
+ return receiverDatas.any { it.receiver == receiver }
+ }
+
+ private fun createFilter(): IntentFilter {
+ val filter = IntentFilter(action)
+ activeCategories.forEach(filter::addCategory)
+ return filter
+ }
+
+ fun removeReceiver(receiver: BroadcastReceiver) {
+ if (receiverDatas.removeAll { it.receiver == receiver } &&
+ receiverDatas.isEmpty() && registered) {
+ unregisterAction()
+ registered = false
+ activeCategories.clear()
+ }
+ }
+
+ @Throws(IllegalStateException::class)
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action != action) {
+ throw(IllegalStateException("Received intent for ${intent.action} " +
+ "in receiver for $action}"))
+ }
+ val id = index.getAndIncrement()
+ logger.logBroadcastReceived(id, userId, intent)
+ // Immediately return control to ActivityManager
+ bgExecutor.execute {
+ receiverDatas.forEach {
+ if (it.filter.matchCategories(intent.categories) == null) {
+ it.executor.execute {
+ it.receiver.pendingResult = pendingResult
+ it.receiver.onReceive(context, intent)
+ logger.logBroadcastDispatched(id, action, it.receiver)
+ }
+ }
+ }
+ }
+ }
+
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.indentIfPossible {
+ println("Registered: $registered")
+ println("Receivers:")
+ pw.indentIfPossible {
+ receiverDatas.forEach {
+ println(it.receiver)
+ }
+ }
+ println("Categories: ${activeCategories.joinToString(", ")}")
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index 67c0c620f136..b9b849b8488e 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -29,6 +29,7 @@ import android.os.UserHandle
import android.text.TextUtils
import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.util.IndentingPrintWriter
import com.android.systemui.Dumpable
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
import com.android.systemui.dump.DumpManager
@@ -65,6 +66,7 @@ private const val DEBUG = true
open class BroadcastDispatcher constructor (
private val context: Context,
private val bgLooper: Looper,
+ private val bgExecutor: Executor,
private val dumpManager: DumpManager,
private val logger: BroadcastDispatcherLogger
) : Dumpable, BroadcastReceiver() {
@@ -173,15 +175,18 @@ open class BroadcastDispatcher constructor (
@VisibleForTesting
protected open fun createUBRForUser(userId: Int) =
- UserBroadcastDispatcher(context, userId, bgLooper, logger)
+ UserBroadcastDispatcher(context, userId, bgLooper, bgExecutor, logger)
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("Broadcast dispatcher:")
- pw.println(" Current user: ${handler.currentUser}")
+ val ipw = IndentingPrintWriter(pw, " ")
+ ipw.increaseIndent()
+ ipw.println("Current user: ${handler.currentUser}")
for (index in 0 until receiversByUser.size()) {
- pw.println(" User ${receiversByUser.keyAt(index)}")
- receiversByUser.valueAt(index).dump(fd, pw, args)
+ ipw.println("User ${receiversByUser.keyAt(index)}")
+ receiversByUser.valueAt(index).dump(fd, ipw, args)
}
+ ipw.decreaseIndent()
}
private val handler = object : Handler(bgLooper) {
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index 96f5a1f6fbe8..11da920d69ed 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -18,8 +18,6 @@ package com.android.systemui.broadcast
import android.content.BroadcastReceiver
import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
import android.os.Handler
import android.os.Looper
import android.os.Message
@@ -31,11 +29,10 @@ import androidx.annotation.VisibleForTesting
import com.android.internal.util.Preconditions
import com.android.systemui.Dumpable
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
+import com.android.systemui.util.indentIfPossible
import java.io.FileDescriptor
import java.io.PrintWriter
-import java.lang.IllegalArgumentException
-import java.lang.IllegalStateException
-import java.util.concurrent.atomic.AtomicBoolean
+import java.util.concurrent.Executor
import java.util.concurrent.atomic.AtomicInteger
private const val MSG_REGISTER_RECEIVER = 0
@@ -48,16 +45,14 @@ private const val DEBUG = false
*
* Created by [BroadcastDispatcher] as needed by users. The value of [userId] can be
* [UserHandle.USER_ALL].
- *
- * Each instance of this class will register itself exactly once with [Context]. Updates to the
- * [IntentFilter] will be done in the background thread.
*/
-class UserBroadcastDispatcher(
+open class UserBroadcastDispatcher(
private val context: Context,
private val userId: Int,
private val bgLooper: Looper,
+ private val bgExecutor: Executor,
private val logger: BroadcastDispatcherLogger
-) : BroadcastReceiver(), Dumpable {
+) : Dumpable {
companion object {
// Used only for debugging. If not debugging, this variable will not be accessed and all
@@ -76,47 +71,16 @@ class UserBroadcastDispatcher(
}
}
- private val registered = AtomicBoolean(false)
-
- internal fun isRegistered() = registered.get()
-
// Only modify in BG thread
- private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>()
- private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
+ @VisibleForTesting
+ internal val actionsToActionsReceivers = ArrayMap<String, ActionReceiver>()
+ private val receiverToActions = ArrayMap<BroadcastReceiver, MutableSet<String>>()
@VisibleForTesting
internal fun isReceiverReferenceHeld(receiver: BroadcastReceiver): Boolean {
- return receiverToReceiverData.contains(receiver) ||
- actionsToReceivers.any {
- it.value.any { it.receiver == receiver }
- }
- }
-
- // Only call on BG thread as it reads from the maps
- private fun createFilter(): IntentFilter {
- Preconditions.checkState(bgHandler.looper.isCurrentThread,
- "This method should only be called from BG thread")
- val categories = mutableSetOf<String>()
- receiverToReceiverData.values.flatten().forEach {
- it.filter.categoriesIterator()?.asSequence()?.let {
- categories.addAll(it)
- }
- }
- val intentFilter = IntentFilter().apply {
- // The keys of the arrayMap are of type String! so null check is needed
- actionsToReceivers.keys.forEach { if (it != null) addAction(it) else Unit }
- categories.forEach { addCategory(it) }
- }
- return intentFilter
- }
-
- override fun onReceive(context: Context, intent: Intent) {
- val id = index.getAndIncrement()
- if (DEBUG) Log.w(TAG, "[$id] Received $intent")
- logger.logBroadcastReceived(id, userId, intent)
- bgHandler.post(
- HandleBroadcastRunnable(
- actionsToReceivers, context, intent, pendingResult, id, logger))
+ return actionsToActionsReceivers.values.any {
+ it.hasReceiver(receiver)
+ } || (receiver in receiverToActions)
}
/**
@@ -137,109 +101,57 @@ class UserBroadcastDispatcher(
Preconditions.checkState(bgHandler.looper.isCurrentThread,
"This method should only be called from BG thread")
if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}")
- receiverToReceiverData.getOrPut(receiverData.receiver, { ArraySet() }).add(receiverData)
- var changed = false
- // Index the BroadcastReceiver by all its actions, that way it's easier to dispatch given
- // a received intent.
+ receiverToActions
+ .getOrPut(receiverData.receiver, { ArraySet() })
+ .addAll(receiverData.filter.actionsIterator()?.asSequence() ?: emptySequence())
receiverData.filter.actionsIterator().forEach {
- actionsToReceivers.getOrPut(it) {
- changed = true
- ArraySet()
- }.add(receiverData)
+ actionsToActionsReceivers
+ .getOrPut(it, { createActionReceiver(it) })
+ .addReceiverData(receiverData)
}
logger.logReceiverRegistered(userId, receiverData.receiver)
- if (changed) {
- createFilterAndRegisterReceiverBG()
- }
+ }
+
+ @VisibleForTesting
+ internal open fun createActionReceiver(action: String): ActionReceiver {
+ return ActionReceiver(
+ action,
+ userId,
+ {
+ context.registerReceiverAsUser(this, UserHandle.of(userId), it, null, bgHandler)
+ logger.logContextReceiverRegistered(userId, it)
+ },
+ {
+ try {
+ context.unregisterReceiver(this)
+ logger.logContextReceiverUnregistered(userId, action)
+ } catch (e: IllegalArgumentException) {
+ Log.e(TAG, "Trying to unregister unregistered receiver for user $userId, " +
+ "action $action",
+ IllegalStateException(e))
+ }
+ },
+ bgExecutor,
+ logger
+ )
}
private fun handleUnregisterReceiver(receiver: BroadcastReceiver) {
Preconditions.checkState(bgHandler.looper.isCurrentThread,
"This method should only be called from BG thread")
if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
- val actions = receiverToReceiverData.getOrElse(receiver) { return }
- .flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet()
- receiverToReceiverData.remove(receiver)?.clear()
- var changed = false
- actions.forEach { action ->
- actionsToReceivers.get(action)?.removeIf { it.receiver == receiver }
- if (actionsToReceivers.get(action)?.isEmpty() ?: false) {
- changed = true
- actionsToReceivers.remove(action)
- }
+ receiverToActions.getOrDefault(receiver, mutableSetOf()).forEach {
+ actionsToActionsReceivers.get(it)?.removeReceiver(receiver)
}
+ receiverToActions.remove(receiver)
logger.logReceiverUnregistered(userId, receiver)
- if (changed) {
- createFilterAndRegisterReceiverBG()
- }
- }
-
- // Only call this from a BG thread
- private fun createFilterAndRegisterReceiverBG() {
- val intentFilter = createFilter()
- bgHandler.post(RegisterReceiverRunnable(intentFilter))
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
- pw.println(" Registered=${registered.get()}")
- actionsToReceivers.forEach { (action, list) ->
- pw.println(" $action:")
- list.forEach { pw.println(" ${it.receiver}") }
- }
- }
-
- private class HandleBroadcastRunnable(
- val actionsToReceivers: Map<String, Set<ReceiverData>>,
- val context: Context,
- val intent: Intent,
- val pendingResult: PendingResult,
- val index: Int,
- val logger: BroadcastDispatcherLogger
- ) : Runnable {
- override fun run() {
- if (DEBUG) Log.w(TAG, "[$index] Dispatching $intent")
- actionsToReceivers.get(intent.action)
- ?.filter {
- it.filter.hasAction(intent.action) &&
- it.filter.matchCategories(intent.categories) == null }
- ?.forEach {
- it.executor.execute {
- if (DEBUG) Log.w(TAG,
- "[$index] Dispatching ${intent.action} to ${it.receiver}")
- logger.logBroadcastDispatched(index, intent.action, it.receiver)
- it.receiver.pendingResult = pendingResult
- it.receiver.onReceive(context, intent)
- }
- }
- }
- }
-
- private inner class RegisterReceiverRunnable(val intentFilter: IntentFilter) : Runnable {
-
- /*
- * Registers and unregisters the BroadcastReceiver
- */
- override fun run() {
- if (registered.get()) {
- try {
- context.unregisterReceiver(this@UserBroadcastDispatcher)
- logger.logContextReceiverUnregistered(userId)
- } catch (e: IllegalArgumentException) {
- Log.e(TAG, "Trying to unregister unregistered receiver for user $userId",
- IllegalStateException(e))
- }
- registered.set(false)
- }
- // Short interval without receiver, this can be problematic
- if (intentFilter.countActions() > 0 && !registered.get()) {
- context.registerReceiverAsUser(
- this@UserBroadcastDispatcher,
- UserHandle.of(userId),
- intentFilter,
- null,
- bgHandler)
- registered.set(true)
- logger.logContextReceiverRegistered(userId, intentFilter)
+ pw.indentIfPossible {
+ actionsToActionsReceivers.forEach { (action, actionReceiver) ->
+ println("$action:")
+ actionReceiver.dump(fd, pw, args)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
index 123a8ae6307d..6ba88f4e69d7 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
@@ -99,11 +99,12 @@ class BroadcastDispatcherLogger @Inject constructor(
})
}
- fun logContextReceiverUnregistered(user: Int) {
+ fun logContextReceiverUnregistered(user: Int, action: String) {
log(INFO, {
int1 = user
+ str1 = action
}, {
- "Receiver unregistered with Context for user $int1."
+ "Receiver unregistered with Context for user $int1, action $str1"
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index 55be77ca3be5..a86a46960bcb 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -100,6 +100,7 @@ public class BadgedImageView extends ImageView {
mDotRenderer = new DotRenderer(mBubbleBitmapSize, iconPath, DEFAULT_PATH_SIZE);
setFocusable(true);
+ setClickable(true);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 7f78ddf2cf1c..a8bbdf6b68c9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -15,7 +15,6 @@
*/
package com.android.systemui.bubbles;
-import static android.app.Notification.FLAG_BUBBLE;
import static android.os.AsyncTask.Status.FINISHED;
import static android.view.Display.INVALID_DISPLAY;
@@ -29,21 +28,19 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Path;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
+import android.graphics.drawable.Icon;
import android.os.UserHandle;
import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.InstanceId;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -57,17 +54,12 @@ import java.util.Objects;
class Bubble implements BubbleViewProvider {
private static final String TAG = "Bubble";
- /**
- * NotificationEntry associated with the bubble. A null value implies this bubble is loaded
- * from disk.
- */
- @Nullable
- private NotificationEntry mEntry;
private final String mKey;
private long mLastUpdated;
private long mLastAccessed;
+ @Nullable
private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
/** Whether the bubble should show a dot for the notification indicating updated content. */
@@ -75,8 +67,6 @@ class Bubble implements BubbleViewProvider {
/** Whether flyout text should be suppressed, regardless of any other flags or state. */
private boolean mSuppressFlyout;
- /** Whether this bubble should auto expand regardless of the normal flag, used for overflow. */
- private boolean mShouldAutoExpand;
// Items that are typically loaded later
private String mAppName;
@@ -87,11 +77,13 @@ class Bubble implements BubbleViewProvider {
private BubbleViewInfoTask mInflationTask;
private boolean mInflateSynchronously;
private boolean mPendingIntentCanceled;
+ private boolean mIsImportantConversation;
/**
* Presentational info about the flyout.
*/
public static class FlyoutMessage {
+ @Nullable public Icon senderIcon;
@Nullable public Drawable senderAvatar;
@Nullable public CharSequence senderName;
@Nullable public CharSequence message;
@@ -109,16 +101,39 @@ class Bubble implements BubbleViewProvider {
private UserHandle mUser;
@NonNull
private String mPackageName;
+ @Nullable
+ private String mTitle;
+ @Nullable
+ private Icon mIcon;
+ private boolean mIsBubble;
+ private boolean mIsVisuallyInterruptive;
+ private boolean mIsClearable;
+ private boolean mShouldSuppressNotificationDot;
+ private boolean mShouldSuppressNotificationList;
+ private boolean mShouldSuppressPeek;
private int mDesiredHeight;
@DimenRes
private int mDesiredHeightResId;
+ /** for logging **/
+ @Nullable
+ private InstanceId mInstanceId;
+ @Nullable
+ private String mChannelId;
+ private int mNotificationId;
+ private int mAppUid = -1;
+
+ @Nullable
+ private PendingIntent mIntent;
+ @Nullable
+ private PendingIntent mDeleteIntent;
+
/**
* Create a bubble with limited information based on given {@link ShortcutInfo}.
* Note: Currently this is only being used when the bubble is persisted to disk.
*/
Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
- final int desiredHeight, final int desiredHeightResId) {
+ final int desiredHeight, final int desiredHeightResId, @Nullable final String title) {
Objects.requireNonNull(key);
Objects.requireNonNull(shortcutInfo);
mShortcutInfo = shortcutInfo;
@@ -126,8 +141,11 @@ class Bubble implements BubbleViewProvider {
mFlags = 0;
mUser = shortcutInfo.getUserHandle();
mPackageName = shortcutInfo.getPackage();
+ mIcon = shortcutInfo.getIcon();
mDesiredHeight = desiredHeight;
mDesiredHeightResId = desiredHeightResId;
+ mTitle = title;
+ mShowBubbleUpdateDot = false;
}
/** Used in tests when no UI is required. */
@@ -145,12 +163,6 @@ class Bubble implements BubbleViewProvider {
return mKey;
}
- @Nullable
- public NotificationEntry getEntry() {
- return mEntry;
- }
-
- @NonNull
public UserHandle getUser() {
return mUser;
}
@@ -203,14 +215,7 @@ class Bubble implements BubbleViewProvider {
@Nullable
public String getTitle() {
- final CharSequence titleCharSeq;
- if (mEntry == null) {
- titleCharSeq = null;
- } else {
- titleCharSeq = mEntry.getSbn().getNotification().extras.getCharSequence(
- Notification.EXTRA_TITLE);
- }
- return titleCharSeq != null ? titleCharSeq.toString() : null;
+ return mTitle;
}
/**
@@ -331,15 +336,45 @@ class Bubble implements BubbleViewProvider {
void setEntry(@NonNull final NotificationEntry entry) {
Objects.requireNonNull(entry);
Objects.requireNonNull(entry.getSbn());
- mEntry = entry;
mLastUpdated = entry.getSbn().getPostTime();
- mFlags = entry.getSbn().getNotification().flags;
+ mIsBubble = entry.getSbn().getNotification().isBubbleNotification();
mPackageName = entry.getSbn().getPackageName();
mUser = entry.getSbn().getUser();
+ mTitle = getTitle(entry);
+ mIsClearable = entry.isClearable();
+ mShouldSuppressNotificationDot = entry.shouldSuppressNotificationDot();
+ mShouldSuppressNotificationList = entry.shouldSuppressNotificationList();
+ mShouldSuppressPeek = entry.shouldSuppressPeek();
+ mChannelId = entry.getSbn().getNotification().getChannelId();
+ mNotificationId = entry.getSbn().getId();
+ mAppUid = entry.getSbn().getUid();
+ mInstanceId = entry.getSbn().getInstanceId();
+ mFlyoutMessage = BubbleViewInfoTask.extractFlyoutMessage(entry);
+ mShortcutInfo = (entry.getBubbleMetadata() != null
+ && entry.getBubbleMetadata().getShortcutId() != null
+ && entry.getRanking() != null) ? entry.getRanking().getShortcutInfo() : null;
+ if (entry.getRanking() != null) {
+ mIsVisuallyInterruptive = entry.getRanking().visuallyInterruptive();
+ }
if (entry.getBubbleMetadata() != null) {
+ mFlags = entry.getBubbleMetadata().getFlags();
mDesiredHeight = entry.getBubbleMetadata().getDesiredHeight();
mDesiredHeightResId = entry.getBubbleMetadata().getDesiredHeightResId();
+ mIcon = entry.getBubbleMetadata().getIcon();
+ mIntent = entry.getBubbleMetadata().getIntent();
+ mDeleteIntent = entry.getBubbleMetadata().getDeleteIntent();
}
+ mIsImportantConversation =
+ entry.getChannel() == null ? false : entry.getChannel().isImportantConversation();
+ }
+
+ @Nullable
+ Icon getIcon() {
+ return mIcon;
+ }
+
+ boolean isVisuallyInterruptive() {
+ return mIsVisuallyInterruptive;
}
/**
@@ -364,6 +399,19 @@ class Bubble implements BubbleViewProvider {
return mExpandedView != null ? mExpandedView.getVirtualDisplayId() : INVALID_DISPLAY;
}
+ public InstanceId getInstanceId() {
+ return mInstanceId;
+ }
+
+ @Nullable
+ public String getChannelId() {
+ return mChannelId;
+ }
+
+ public int getNotificationId() {
+ return mNotificationId;
+ }
+
/**
* Should be invoked whenever a Bubble is accessed (selected while expanded).
*/
@@ -384,24 +432,26 @@ class Bubble implements BubbleViewProvider {
* Whether this notification should be shown in the shade.
*/
boolean showInShade() {
- if (mEntry == null) return false;
- return !shouldSuppressNotification() || !mEntry.isClearable();
+ return !shouldSuppressNotification() || !mIsClearable;
+ }
+
+ /**
+ * Whether this notification conversation is important.
+ */
+ boolean isImportantConversation() {
+ return mIsImportantConversation;
}
/**
* Sets whether this notification should be suppressed in the shade.
*/
void setSuppressNotification(boolean suppressNotification) {
- if (mEntry == null) return;
boolean prevShowInShade = showInShade();
- Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
- int flags = data.getFlags();
if (suppressNotification) {
- flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+ mFlags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
} else {
- flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+ mFlags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
}
- data.setFlags(flags);
if (showInShade() != prevShowInShade && mSuppressionListener != null) {
mSuppressionListener.onBubbleNotificationSuppressionChange(this);
@@ -424,9 +474,8 @@ class Bubble implements BubbleViewProvider {
*/
@Override
public boolean showDot() {
- if (mEntry == null) return false;
return mShowBubbleUpdateDot
- && !mEntry.shouldSuppressNotificationDot()
+ && !mShouldSuppressNotificationDot
&& !shouldSuppressNotification();
}
@@ -434,10 +483,9 @@ class Bubble implements BubbleViewProvider {
* Whether the flyout for the bubble should be shown.
*/
boolean showFlyout() {
- if (mEntry == null) return false;
- return !mSuppressFlyout && !mEntry.shouldSuppressPeek()
+ return !mSuppressFlyout && !mShouldSuppressPeek
&& !shouldSuppressNotification()
- && !mEntry.shouldSuppressNotificationList();
+ && !mShouldSuppressNotificationList;
}
/**
@@ -480,25 +528,14 @@ class Bubble implements BubbleViewProvider {
}
}
- /**
- * Whether shortcut information should be used to populate the bubble.
- * <p>
- * To populate the activity use {@link LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)}.
- * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}.
- */
- boolean usingShortcutInfo() {
- return mEntry != null && mEntry.getBubbleMetadata().getShortcutId() != null
- || mShortcutInfo != null;
+ @Nullable
+ PendingIntent getBubbleIntent() {
+ return mIntent;
}
@Nullable
- PendingIntent getBubbleIntent() {
- if (mEntry == null) return null;
- Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
- if (data != null) {
- return data.getIntent();
- }
- return null;
+ PendingIntent getDeleteIntent() {
+ return mDeleteIntent;
}
Intent getSettingsIntent(final Context context) {
@@ -514,8 +551,12 @@ class Bubble implements BubbleViewProvider {
return intent;
}
+ public int getAppUid() {
+ return mAppUid;
+ }
+
private int getUid(final Context context) {
- if (mEntry != null) return mEntry.getSbn().getUid();
+ if (mAppUid != -1) return mAppUid;
final PackageManager pm = context.getPackageManager();
if (pm == null) return -1;
try {
@@ -548,24 +589,27 @@ class Bubble implements BubbleViewProvider {
}
private boolean shouldSuppressNotification() {
- if (mEntry == null) return true;
- return mEntry.getBubbleMetadata() != null
- && mEntry.getBubbleMetadata().isNotificationSuppressed();
+ return isEnabled(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
}
- boolean shouldAutoExpand() {
- if (mEntry == null) return mShouldAutoExpand;
- Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
- return (metadata != null && metadata.getAutoExpandBubble()) || mShouldAutoExpand;
+ public boolean shouldAutoExpand() {
+ return isEnabled(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
}
void setShouldAutoExpand(boolean shouldAutoExpand) {
- mShouldAutoExpand = shouldAutoExpand;
+ if (shouldAutoExpand) {
+ enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
+ } else {
+ disable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
+ }
+ }
+
+ public void setIsBubble(final boolean isBubble) {
+ mIsBubble = isBubble;
}
public boolean isBubble() {
- if (mEntry == null) return (mFlags & FLAG_BUBBLE) != 0;
- return (mEntry.getSbn().getNotification().flags & FLAG_BUBBLE) != 0;
+ return mIsBubble;
}
public void enable(int option) {
@@ -576,6 +620,10 @@ class Bubble implements BubbleViewProvider {
mFlags &= ~option;
}
+ public boolean isEnabled(int option) {
+ return (mFlags & option) != 0;
+ }
+
@Override
public String toString() {
return "Bubble{" + mKey + '}';
@@ -610,34 +658,24 @@ class Bubble implements BubbleViewProvider {
@Override
public void logUIEvent(int bubbleCount, int action, float normalX, float normalY, int index) {
- if (this.getEntry() == null
- || this.getEntry().getSbn() == null) {
- SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
- null /* package name */,
- null /* notification channel */,
- 0 /* notification ID */,
- 0 /* bubble position */,
- bubbleCount,
- action,
- normalX,
- normalY,
- false /* unread bubble */,
- false /* on-going bubble */,
- false /* isAppForeground (unused) */);
- } else {
- StatusBarNotification notification = this.getEntry().getSbn();
- SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
- notification.getPackageName(),
- notification.getNotification().getChannelId(),
- notification.getId(),
- index,
- bubbleCount,
- action,
- normalX,
- normalY,
- this.showInShade(),
- false /* isOngoing (unused) */,
- false /* isAppForeground (unused) */);
- }
+ SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
+ mPackageName,
+ mChannelId,
+ mNotificationId,
+ index,
+ bubbleCount,
+ action,
+ normalX,
+ normalY,
+ showInShade(),
+ false /* isOngoing (unused) */,
+ false /* isAppForeground (unused) */);
+ }
+
+ @Nullable
+ private static String getTitle(@NonNull final NotificationEntry e) {
+ final CharSequence titleCharSeq = e.getSbn().getNotification().extras.getCharSequence(
+ Notification.EXTRA_TITLE);
+ return titleCharSeq == null ? null : titleCharSeq.toString();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index c4c5da42ec06..500f991f4200 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -67,6 +67,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.SparseSetArray;
import android.view.Display;
+import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -182,6 +183,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// Only load overflow data from disk once
private boolean mOverflowDataLoaded = false;
+ /**
+ * When the shade status changes to SHADE (from anything but SHADE, like LOCKED) we'll select
+ * this bubble and expand the stack.
+ */
+ @Nullable private NotificationEntry mNotifEntryToExpandOnShadeUnlock;
+
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private IStatusBarService mBarService;
private WindowManager mWindowManager;
@@ -206,6 +213,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
*/
private int mDensityDpi = Configuration.DENSITY_DPI_UNDEFINED;
+ /** Last known direction, used to detect layout direction changes @link #onConfigChanged}. */
+ private int mLayoutDirection = View.LAYOUT_DIRECTION_UNDEFINED;
+
private boolean mInflateSynchronously;
// TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline
@@ -291,6 +301,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (shouldCollapse) {
collapseStack();
}
+
+ if (mNotifEntryToExpandOnShadeUnlock != null) {
+ expandStackAndSelectBubble(mNotifEntryToExpandOnShadeUnlock);
+ mNotifEntryToExpandOnShadeUnlock = null;
+ }
+
updateStack();
}
}
@@ -394,6 +410,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
: statusBarService;
mBubbleScrim = new ScrimView(mContext);
+ mBubbleScrim.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
mSavedBubbleKeysPerUser = new SparseSetArray<>();
mCurrentUserId = mNotifUserManager.getCurrentUserId();
@@ -505,8 +522,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
addNotifCallback(new NotifCallback() {
@Override
public void removeNotification(NotificationEntry entry, int reason) {
- mNotificationEntryManager.performRemoveNotification(entry.getSbn(),
- reason);
+ mNotificationEntryManager.performRemoveNotification(entry.getSbn(), reason);
}
@Override
@@ -637,8 +653,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mStackView.setExpandListener(mExpandListener);
}
- mStackView.setUnbubbleConversationCallback(notificationEntry ->
- onUserChangedBubble(notificationEntry, false /* shouldBubble */));
+ mStackView.setUnbubbleConversationCallback(key -> {
+ final NotificationEntry entry =
+ mNotificationEntryManager.getPendingOrActiveNotif(key);
+ if (entry != null) {
+ onUserChangedBubble(entry, false /* shouldBubble */);
+ }
+ });
}
addToWindowManagerMaybe();
@@ -826,8 +847,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mBubbleIconFactory = new BubbleIconFactory(mContext);
mStackView.onDisplaySizeChanged();
}
-
- mStackView.onLayoutDirectionChanged();
+ if (newConfig.getLayoutDirection() != mLayoutDirection) {
+ mLayoutDirection = newConfig.getLayoutDirection();
+ mStackView.onLayoutDirectionChanged(mLayoutDirection);
+ }
}
}
@@ -924,20 +947,29 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
* @param entry the notification for the bubble to be selected
*/
public void expandStackAndSelectBubble(NotificationEntry entry) {
- String key = entry.getKey();
- Bubble bubble = mBubbleData.getBubbleInStackWithKey(key);
- if (bubble != null) {
- mBubbleData.setSelectedBubble(bubble);
- mBubbleData.setExpanded(true);
- } else {
- bubble = mBubbleData.getOverflowBubbleWithKey(key);
+ if (mStatusBarStateListener.getCurrentState() == SHADE) {
+ mNotifEntryToExpandOnShadeUnlock = null;
+
+ String key = entry.getKey();
+ Bubble bubble = mBubbleData.getBubbleInStackWithKey(key);
if (bubble != null) {
- promoteBubbleFromOverflow(bubble);
- } else if (entry.canBubble()) {
- // It can bubble but it's not -- it got aged out of the overflow before it
- // was dismissed or opened, make it a bubble again.
- setIsBubble(entry, true /* isBubble */, true /* autoExpand */);
+ mBubbleData.setSelectedBubble(bubble);
+ mBubbleData.setExpanded(true);
+ } else {
+ bubble = mBubbleData.getOverflowBubbleWithKey(key);
+ if (bubble != null) {
+ promoteBubbleFromOverflow(bubble);
+ } else if (entry.canBubble()) {
+ // It can bubble but it's not -- it got aged out of the overflow before it
+ // was dismissed or opened, make it a bubble again.
+ setIsBubble(entry, true /* isBubble */, true /* autoExpand */);
+ }
}
+ } else {
+ // Wait until we're unlocked to expand, so that the user can see the expand animation
+ // and also to work around bugs with expansion animation + shade unlock happening at the
+ // same time.
+ mNotifEntryToExpandOnShadeUnlock = entry;
}
}
@@ -1024,10 +1056,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
* @param entry the notification to change bubble state for.
* @param shouldBubble whether the notification should show as a bubble or not.
*/
- public void onUserChangedBubble(@Nullable final NotificationEntry entry, boolean shouldBubble) {
- if (entry == null) {
- return;
- }
+ public void onUserChangedBubble(@NonNull final NotificationEntry entry, boolean shouldBubble) {
NotificationChannel channel = entry.getChannel();
final String appPkg = entry.getSbn().getPackageName();
final int appUid = entry.getSbn().getUid();
@@ -1103,7 +1132,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mBubbleData.removeSuppressedSummary(groupKey);
// Remove any associated bubble children with the summary
- final List<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
+ final List<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(
+ groupKey, mNotificationEntryManager);
for (int i = 0; i < bubbleChildren.size(); i++) {
removeBubble(bubbleChildren.get(i).getKey(), DISMISS_GROUP_CANCELLED);
}
@@ -1161,21 +1191,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private void setIsBubble(@NonNull final Bubble b, final boolean isBubble) {
Objects.requireNonNull(b);
- if (isBubble) {
- b.enable(FLAG_BUBBLE);
- } else {
- b.disable(FLAG_BUBBLE);
- }
- if (b.getEntry() != null) {
+ b.setIsBubble(isBubble);
+ final NotificationEntry entry = mNotificationEntryManager
+ .getPendingOrActiveNotif(b.getKey());
+ if (entry != null) {
// Updating the entry to be a bubble will trigger our normal update flow
- setIsBubble(b.getEntry(), isBubble, b.shouldAutoExpand());
+ setIsBubble(entry, isBubble, b.shouldAutoExpand());
} else if (isBubble) {
- // If we have no entry to update, it's a persisted bubble so
- // we need to add it to the stack ourselves
+ // If bubble doesn't exist, it's a persisted bubble so we need to add it to the
+ // stack ourselves
Bubble bubble = mBubbleData.getOrCreateBubble(null, b /* persistedBubble */);
inflateAndAdd(bubble, bubble.shouldAutoExpand() /* suppressFlyout */,
!bubble.shouldAutoExpand() /* showInShade */);
-
}
}
@@ -1214,6 +1241,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (reason == DISMISS_NOTIF_CANCEL) {
bubblesToBeRemovedFromRepository.add(bubble);
}
+ final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(
+ bubble.getKey());
if (!mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
if (!mBubbleData.hasOverflowBubbleWithKey(bubble.getKey())
&& (!bubble.showInShade()
@@ -1222,26 +1251,27 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// The bubble is now gone & the notification is hidden from the shade, so
// time to actually remove it
for (NotifCallback cb : mCallbacks) {
- if (bubble.getEntry() != null) {
- cb.removeNotification(bubble.getEntry(), REASON_CANCEL);
+ if (entry != null) {
+ cb.removeNotification(entry, REASON_CANCEL);
}
}
} else {
if (bubble.isBubble()) {
setIsBubble(bubble, false /* isBubble */);
}
- if (bubble.getEntry() != null && bubble.getEntry().getRow() != null) {
- bubble.getEntry().getRow().updateBubbleButton();
+ if (entry != null && entry.getRow() != null) {
+ entry.getRow().updateBubbleButton();
}
}
}
- if (bubble.getEntry() != null) {
- final String groupKey = bubble.getEntry().getSbn().getGroupKey();
- if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
+ if (entry != null) {
+ final String groupKey = entry.getSbn().getGroupKey();
+ if (mBubbleData.getBubblesInGroup(
+ groupKey, mNotificationEntryManager).isEmpty()) {
// Time to potentially remove the summary
for (NotifCallback cb : mCallbacks) {
- cb.maybeCancelSummary(bubble.getEntry());
+ cb.maybeCancelSummary(entry);
}
}
}
@@ -1266,9 +1296,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (update.selectionChanged && mStackView != null) {
mStackView.setSelectedBubble(update.selectedBubble);
- if (update.selectedBubble != null && update.selectedBubble.getEntry() != null) {
- mNotificationGroupManager.updateSuppression(
- update.selectedBubble.getEntry());
+ if (update.selectedBubble != null) {
+ final NotificationEntry entry = mNotificationEntryManager
+ .getPendingOrActiveNotif(update.selectedBubble.getKey());
+ if (entry != null) {
+ mNotificationGroupManager.updateSuppression(entry);
+ }
}
}
@@ -1341,7 +1374,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
String groupKey = entry.getSbn().getGroupKey();
- ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
+ ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(
+ groupKey, mNotificationEntryManager);
boolean isSuppressedSummary = (mBubbleData.isSummarySuppressed(groupKey)
&& mBubbleData.getSummaryKey(groupKey).equals(entry.getKey()));
boolean isSummary = entry.getSbn().getNotification().isGroupSummary();
@@ -1361,9 +1395,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// As far as group manager is concerned, once a child is no longer shown
// in the shade, it is essentially removed.
Bubble bubbleChild = mBubbleData.getAnyBubbleWithkey(child.getKey());
- mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry());
- bubbleChild.setSuppressNotification(true);
- bubbleChild.setShowDot(false /* show */);
+ if (bubbleChild != null) {
+ final NotificationEntry entry = mNotificationEntryManager
+ .getPendingOrActiveNotif(bubbleChild.getKey());
+ if (entry != null) {
+ mNotificationGroupManager.onEntryRemoved(entry);
+ }
+ bubbleChild.setSuppressNotification(true);
+ bubbleChild.setShowDot(false /* show */);
+ }
} else {
// non-bubbled children can be removed
for (NotifCallback cb : mCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 20a9a8cf324c..c8706126c1ad 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -22,7 +22,6 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
import android.annotation.NonNull;
-import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.util.Log;
@@ -34,6 +33,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController.DismissReason;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.io.FileDescriptor;
@@ -256,8 +256,7 @@ public class BubbleData {
}
mPendingBubbles.remove(bubble.getKey()); // No longer pending once we're here
Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey());
- suppressFlyout |= bubble.getEntry() == null
- || !bubble.getEntry().getRanking().visuallyInterruptive();
+ suppressFlyout |= !bubble.isVisuallyInterruptive();
if (prevBubble == null) {
// Create a new bubble
@@ -335,13 +334,15 @@ public class BubbleData {
* Retrieves any bubbles that are part of the notification group represented by the provided
* group key.
*/
- ArrayList<Bubble> getBubblesInGroup(@Nullable String groupKey) {
+ ArrayList<Bubble> getBubblesInGroup(@Nullable String groupKey, @NonNull
+ NotificationEntryManager nem) {
ArrayList<Bubble> bubbleChildren = new ArrayList<>();
if (groupKey == null) {
return bubbleChildren;
}
for (Bubble b : mBubbles) {
- if (b.getEntry() != null && groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
+ final NotificationEntry entry = nem.getPendingOrActiveNotif(b.getKey());
+ if (entry != null && groupKey.equals(entry.getSbn().getGroupKey())) {
bubbleChildren.add(b);
}
}
@@ -439,9 +440,7 @@ public class BubbleData {
Bubble newSelected = mBubbles.get(newIndex);
setSelectedBubbleInternal(newSelected);
}
- if (bubbleToRemove.getEntry() != null) {
- maybeSendDeleteIntent(reason, bubbleToRemove.getEntry());
- }
+ maybeSendDeleteIntent(reason, bubbleToRemove);
}
void overflowBubble(@DismissReason int reason, Bubble bubble) {
@@ -611,21 +610,14 @@ public class BubbleData {
return true;
}
- private void maybeSendDeleteIntent(@DismissReason int reason,
- @NonNull final NotificationEntry entry) {
- if (reason == BubbleController.DISMISS_USER_GESTURE) {
- Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata();
- PendingIntent deleteIntent = bubbleMetadata != null
- ? bubbleMetadata.getDeleteIntent()
- : null;
- if (deleteIntent != null) {
- try {
- deleteIntent.send();
- } catch (PendingIntent.CanceledException e) {
- Log.w(TAG, "Failed to send delete intent for bubble with key: "
- + entry.getKey());
- }
- }
+ private void maybeSendDeleteIntent(@DismissReason int reason, @NonNull final Bubble bubble) {
+ if (reason != BubbleController.DISMISS_USER_GESTURE) return;
+ PendingIntent deleteIntent = bubble.getDeleteIntent();
+ if (deleteIntent == null) return;
+ try {
+ deleteIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "Failed to send delete intent for bubble with key: " + bubble.getKey());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
index d20f40559b5d..390f7064a227 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
@@ -74,11 +74,15 @@ internal class BubbleDataRepository @Inject constructor(
private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> {
return bubbles.mapNotNull { b ->
- var shortcutId = b.shortcutInfo?.id
- if (shortcutId == null) shortcutId = b.entry?.bubbleMetadata?.shortcutId
- if (shortcutId == null) return@mapNotNull null
- BubbleEntity(userId, b.packageName, shortcutId, b.key, b.rawDesiredHeight,
- b.rawDesiredHeightResId)
+ BubbleEntity(
+ userId,
+ b.packageName,
+ b.shortcutInfo?.id ?: return@mapNotNull null,
+ b.key,
+ b.rawDesiredHeight,
+ b.rawDesiredHeightResId,
+ b.title
+ )
}
}
@@ -158,9 +162,14 @@ internal class BubbleDataRepository @Inject constructor(
// into Bubble.
val bubbles = entities.mapNotNull { entity ->
shortcutMap[ShortcutKey(entity.userId, entity.packageName)]
- ?.first { shortcutInfo -> entity.shortcutId == shortcutInfo.id }
- ?.let { shortcutInfo -> Bubble(entity.key, shortcutInfo, entity.desiredHeight,
- entity.desiredHeightResId) }
+ ?.firstOrNull { shortcutInfo -> entity.shortcutId == shortcutInfo.id }
+ ?.let { shortcutInfo -> Bubble(
+ entity.key,
+ shortcutInfo,
+ entity.desiredHeight,
+ entity.desiredHeightResId,
+ entity.title
+ ) }
}
uiScope.launch { cb(bubbles) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index bc03bf981914..8722ac9a36b5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -120,6 +120,8 @@ public class BubbleExpandedView extends LinearLayout {
private int mPointerWidth;
private int mPointerHeight;
private ShapeDrawable mPointerDrawable;
+ private int mExpandedViewPadding;
+
@Nullable private Bubble mBubble;
@@ -171,7 +173,7 @@ public class BubbleExpandedView extends LinearLayout {
return;
}
try {
- if (!mIsOverflow && mBubble.usingShortcutInfo()) {
+ if (!mIsOverflow && mBubble.getShortcutInfo() != null) {
options.setApplyActivityFlagsForBubbles(true);
mActivityView.startShortcutActivity(mBubble.getShortcutInfo(),
options, null /* sourceBounds */);
@@ -345,11 +347,9 @@ public class BubbleExpandedView extends LinearLayout {
return view.onApplyWindowInsets(insets);
});
- final int expandedViewPadding =
- res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
-
- setPadding(
- expandedViewPadding, expandedViewPadding, expandedViewPadding, expandedViewPadding);
+ mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
+ setPadding(mExpandedViewPadding, mExpandedViewPadding, mExpandedViewPadding,
+ mExpandedViewPadding);
setOnTouchListener((view, motionEvent) -> {
if (!usingActivityView()) {
return false;
@@ -668,7 +668,7 @@ public class BubbleExpandedView extends LinearLayout {
desiredHeight = Math.max(mBubble.getDesiredHeight(mContext), mMinHeight);
}
float height = Math.min(desiredHeight, getMaxExpandedHeight());
- height = Math.max(height, mIsOverflow? mOverflowHeight : mMinHeight);
+ height = Math.max(height, mMinHeight);
ViewGroup.LayoutParams lp = mActivityView.getLayoutParams();
mNeedsNewHeight = lp.height != height;
if (!mKeyboardVisible) {
@@ -729,7 +729,7 @@ public class BubbleExpandedView extends LinearLayout {
*/
public void setPointerPosition(float x) {
float halfPointerWidth = mPointerWidth / 2f;
- float pointerLeft = x - halfPointerWidth;
+ float pointerLeft = x - halfPointerWidth - mExpandedViewPadding;
mPointerView.setTranslationX(pointerLeft);
mPointerView.setVisibility(VISIBLE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
index 8c76cda3290f..1fa3aaae5e61 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
@@ -31,6 +31,7 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.text.TextUtils;
import android.view.LayoutInflater;
@@ -223,9 +224,10 @@ public class BubbleFlyoutView extends FrameLayout {
float[] dotCenter,
boolean hideDot) {
- if (flyoutMessage.senderAvatar != null && flyoutMessage.isGroupChat) {
+ final Drawable senderAvatar = flyoutMessage.senderAvatar;
+ if (senderAvatar != null && flyoutMessage.isGroupChat) {
mSenderAvatar.setVisibility(VISIBLE);
- mSenderAvatar.setImageDrawable(flyoutMessage.senderAvatar);
+ mSenderAvatar.setImageDrawable(senderAvatar);
} else {
mSenderAvatar.setVisibility(GONE);
mSenderAvatar.setTranslationX(0);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
index 74231c648f00..40a93e1cdc47 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
@@ -15,13 +15,16 @@
*/
package com.android.systemui.bubbles;
-import android.app.Notification;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -50,15 +53,14 @@ public class BubbleIconFactory extends BaseIconFactory {
/**
* Returns the drawable that the developer has provided to display in the bubble.
*/
- Drawable getBubbleDrawable(Context context, ShortcutInfo shortcutInfo,
- Notification.BubbleMetadata metadata) {
+ Drawable getBubbleDrawable(@NonNull final Context context,
+ @Nullable final ShortcutInfo shortcutInfo, @Nullable final Icon ic) {
if (shortcutInfo != null) {
LauncherApps launcherApps =
(LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
int density = context.getResources().getConfiguration().densityDpi;
return launcherApps.getShortcutIconDrawable(shortcutInfo, density);
} else {
- Icon ic = metadata.getIcon();
if (ic != null) {
if (ic.getType() == Icon.TYPE_URI
|| ic.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
@@ -76,15 +78,36 @@ public class BubbleIconFactory extends BaseIconFactory {
* Returns a {@link BitmapInfo} for the app-badge that is shown on top of each bubble. This
* will include the workprofile indicator on the badge if appropriate.
*/
- BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon) {
+ BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
Bitmap userBadgedBitmap = createIconBitmap(
userBadgedAppIcon, 1f, getBadgeSize());
-
- Canvas c = new Canvas();
ShadowGenerator shadowGenerator = new ShadowGenerator(getBadgeSize());
- c.setBitmap(userBadgedBitmap);
- shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
- return createIconBitmap(userBadgedBitmap);
+ if (!isImportantConversation) {
+ Canvas c = new Canvas();
+ c.setBitmap(userBadgedBitmap);
+ shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
+ return createIconBitmap(userBadgedBitmap);
+ } else {
+ float ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.importance_ring_stroke_width);
+ int importantConversationColor = mContext.getResources().getColor(
+ com.android.settingslib.R.color.important_conversation, null);
+ Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(),
+ userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig());
+ Canvas c = new Canvas(badgeAndRing);
+ Rect dest = new Rect((int) ringStrokeWidth, (int) ringStrokeWidth,
+ c.getHeight() - (int) ringStrokeWidth, c.getWidth() - (int) ringStrokeWidth);
+ c.drawBitmap(userBadgedBitmap, null, dest, null);
+ Paint ringPaint = new Paint();
+ ringPaint.setStyle(Paint.Style.STROKE);
+ ringPaint.setColor(importantConversationColor);
+ ringPaint.setAntiAlias(true);
+ ringPaint.setStrokeWidth(ringStrokeWidth);
+ c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2 - ringStrokeWidth,
+ ringPaint);
+ shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c);
+ return createIconBitmap(badgeAndRing);
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java
index c5faae0d703e..c1dd8c36ff6f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java
@@ -16,8 +16,6 @@
package com.android.systemui.bubbles;
-import android.service.notification.StatusBarNotification;
-
import com.android.internal.logging.UiEventLoggerImpl;
/**
@@ -32,12 +30,11 @@ public class BubbleLoggerImpl extends UiEventLoggerImpl implements BubbleLogger
* @param e UI event
*/
public void log(Bubble b, UiEventEnum e) {
- if (b.getEntry() == null) {
+ if (b.getInstanceId() == null) {
// Added from persistence -- TODO log this with specific event?
return;
}
- StatusBarNotification sbn = b.getEntry().getSbn();
- logWithInstanceId(e, sbn.getUid(), sbn.getPackageName(), sbn.getInstanceId());
+ logWithInstanceId(e, b.getAppUid(), b.getPackageName(), b.getInstanceId());
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleManageEducationView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleManageEducationView.java
index 47120124a55f..86244ba5248a 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleManageEducationView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleManageEducationView.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
+import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -34,6 +35,8 @@ import com.android.systemui.R;
public class BubbleManageEducationView extends LinearLayout {
private View mManageView;
+ private TextView mTitleTextView;
+ private TextView mDescTextView;
public BubbleManageEducationView(Context context) {
this(context, null);
@@ -57,6 +60,8 @@ public class BubbleManageEducationView extends LinearLayout {
super.onFinishInflate();
mManageView = findViewById(R.id.manage_education_view);
+ mTitleTextView = findViewById(R.id.user_education_title);
+ mDescTextView = findViewById(R.id.user_education_description);
final TypedArray ta = mContext.obtainStyledAttributes(
new int[] {android.R.attr.colorAccent,
@@ -66,8 +71,8 @@ public class BubbleManageEducationView extends LinearLayout {
ta.recycle();
textColor = ContrastColorUtil.ensureTextContrast(textColor, bgColor, true);
- ((TextView) findViewById(R.id.user_education_title)).setTextColor(textColor);
- ((TextView) findViewById(R.id.user_education_description)).setTextColor(textColor);
+ mTitleTextView.setTextColor(textColor);
+ mDescTextView.setTextColor(textColor);
}
/**
@@ -84,4 +89,18 @@ public class BubbleManageEducationView extends LinearLayout {
public int getManageViewHeight() {
return mManageView.getHeight();
}
+
+ @Override
+ public void setLayoutDirection(int direction) {
+ super.setLayoutDirection(direction);
+ if (getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ mManageView.setBackgroundResource(R.drawable.bubble_stack_user_education_bg_rtl);
+ mTitleTextView.setGravity(Gravity.RIGHT);
+ mDescTextView.setGravity(Gravity.RIGHT);
+ } else {
+ mManageView.setBackgroundResource(R.drawable.bubble_stack_user_education_bg);
+ mTitleTextView.setGravity(Gravity.LEFT);
+ mDescTextView.setGravity(Gravity.LEFT);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index b644079be565..7408fb3de019 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -22,12 +22,10 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME
import android.app.Activity;
import android.content.Context;
-import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -290,20 +288,10 @@ class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.V
}
});
- // If the bubble was persisted, the entry is null but it should have shortcut info
- ShortcutInfo info = b.getEntry() == null
- ? b.getShortcutInfo()
- : b.getEntry().getRanking().getShortcutInfo();
- if (info == null) {
- Log.d(TAG, "ShortcutInfo required to bubble but none found for " + b);
- } else {
- CharSequence label = info.getLabel();
- if (label == null) {
- vh.textView.setText(b.getAppName());
- } else {
- vh.textView.setText(label.toString());
- }
- }
+ CharSequence label = b.getShortcutInfo() != null
+ ? b.getShortcutInfo().getLabel()
+ : b.getAppName();
+ vh.textView.setText(label);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 26ed1d121acb..10bfcda90edb 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -70,6 +70,7 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.MainThread;
@@ -92,7 +93,6 @@ import com.android.systemui.bubbles.animation.StackAnimationController;
import com.android.systemui.model.SysUiState;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.util.DismissCircleView;
import com.android.systemui.util.FloatingContentCoordinator;
@@ -303,7 +303,7 @@ public class BubbleStackView extends FrameLayout
private BubbleController.BubbleExpandListener mExpandListener;
/** Callback to run when we want to unbubble the given notification's conversation. */
- private Consumer<NotificationEntry> mUnbubbleConversationCallback;
+ private Consumer<String> mUnbubbleConversationCallback;
private SysUiState mSysUiState;
@@ -890,14 +890,7 @@ public class BubbleStackView extends FrameLayout
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
mStackAnimationController.updateResources(mOrientation);
-
- // Reposition & adjust the height for new orientation
- if (mIsExpanded) {
- mExpandedViewContainer.setTranslationY(getExpandedViewY());
- if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
- mExpandedBubble.getExpandedView().updateView(getLocationOnScreen());
- }
- }
+ mBubbleOverflow.updateDimensions();
// Need to update the padding around the view
WindowInsets insets = getRootWindowInsets();
@@ -921,9 +914,15 @@ public class BubbleStackView extends FrameLayout
if (mIsExpanded) {
// Re-draw bubble row and pointer for new orientation.
+ beforeExpandedViewAnimation();
+ updateOverflowVisibility();
+ updatePointerPosition();
mExpandedAnimationController.expandFromStack(() -> {
- updatePointerPosition();
+ afterExpandedViewAnimation();
} /* after */);
+ mExpandedViewContainer.setTranslationX(0);
+ mExpandedViewContainer.setTranslationY(getExpandedViewY());
+ mExpandedViewContainer.setAlpha(1f);
}
if (mVerticalPosPercentBeforeRotation >= 0) {
mStackAnimationController.moveStackToSimilarPositionAfterRotation(
@@ -1057,10 +1056,7 @@ public class BubbleStackView extends FrameLayout
mManageMenu.findViewById(R.id.bubble_manage_menu_dont_bubble_container).setOnClickListener(
view -> {
showManageMenu(false /* show */);
- final Bubble bubble = mBubbleData.getSelectedBubble();
- if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
- mUnbubbleConversationCallback.accept(bubble.getEntry());
- }
+ mUnbubbleConversationCallback.accept(mBubbleData.getSelectedBubble().getKey());
});
mManageMenu.findViewById(R.id.bubble_manage_menu_settings_container).setOnClickListener(
@@ -1070,10 +1066,8 @@ public class BubbleStackView extends FrameLayout
if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
final Intent intent = bubble.getSettingsIntent(mContext);
collapseStack(() -> {
-
mContext.startActivityAsUser(intent, bubble.getUser());
- logBubbleClickEvent(
- bubble,
+ logBubbleEvent(bubble,
SysUiStatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
});
}
@@ -1113,6 +1107,7 @@ public class BubbleStackView extends FrameLayout
title.setTextColor(textColor);
description.setTextColor(textColor);
+ updateUserEducationForLayoutDirection();
addView(mUserEducationView);
}
@@ -1129,7 +1124,7 @@ public class BubbleStackView extends FrameLayout
false /* attachToRoot */);
mManageEducationView.setVisibility(GONE);
mManageEducationView.setElevation(mBubbleElevation);
-
+ mManageEducationView.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
addView(mManageEducationView);
}
}
@@ -1211,13 +1206,17 @@ public class BubbleStackView extends FrameLayout
}
/** Tells the views with locale-dependent layout direction to resolve the new direction. */
- public void onLayoutDirectionChanged() {
- mManageMenu.resolveLayoutDirection();
- mFlyout.resolveLayoutDirection();
-
- if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
- mExpandedBubble.getExpandedView().resolveLayoutDirection();
+ public void onLayoutDirectionChanged(int direction) {
+ mManageMenu.setLayoutDirection(direction);
+ mFlyout.setLayoutDirection(direction);
+ if (mUserEducationView != null) {
+ mUserEducationView.setLayoutDirection(direction);
+ updateUserEducationForLayoutDirection();
+ }
+ if (mManageEducationView != null) {
+ mManageEducationView.setLayoutDirection(direction);
}
+ updateExpandedViewDirection(direction);
}
/** Respond to the display size change by recalculating view size and location. */
@@ -1292,6 +1291,18 @@ public class BubbleStackView extends FrameLayout
});
}
+ void updateExpandedViewDirection(int direction) {
+ final List<Bubble> bubbles = mBubbleData.getBubbles();
+ if (bubbles.isEmpty()) {
+ return;
+ }
+ bubbles.forEach(bubble -> {
+ if (bubble.getExpandedView() != null) {
+ bubble.getExpandedView().setLayoutDirection(direction);
+ }
+ });
+ }
+
void setupLocalMenu(AccessibilityNodeInfo info) {
Resources res = mContext.getResources();
@@ -1412,7 +1423,7 @@ public class BubbleStackView extends FrameLayout
/** Sets the function to call to un-bubble the given conversation. */
public void setUnbubbleConversationCallback(
- Consumer<NotificationEntry> unbubbleConversationCallback) {
+ Consumer<String> unbubbleConversationCallback) {
mUnbubbleConversationCallback = unbubbleConversationCallback;
}
@@ -1639,6 +1650,8 @@ public class BubbleStackView extends FrameLayout
if (mShouldShowUserEducation && mUserEducationView.getVisibility() != VISIBLE) {
mUserEducationView.setAlpha(0);
mUserEducationView.setVisibility(VISIBLE);
+ updateUserEducationForLayoutDirection();
+
// Post so we have height of mUserEducationView
mUserEducationView.post(() -> {
final int viewHeight = mUserEducationView.getHeight();
@@ -1656,6 +1669,28 @@ public class BubbleStackView extends FrameLayout
return false;
}
+ private void updateUserEducationForLayoutDirection() {
+ if (mUserEducationView == null) {
+ return;
+ }
+ LinearLayout textLayout = mUserEducationView.findViewById(R.id.user_education_view);
+ TextView title = mUserEducationView.findViewById(R.id.user_education_title);
+ TextView description = mUserEducationView.findViewById(R.id.user_education_description);
+ boolean isLtr =
+ getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_LTR;
+ if (isLtr) {
+ mUserEducationView.setLayoutDirection(LAYOUT_DIRECTION_LTR);
+ textLayout.setBackgroundResource(R.drawable.bubble_stack_user_education_bg);
+ title.setGravity(Gravity.LEFT);
+ description.setGravity(Gravity.LEFT);
+ } else {
+ mUserEducationView.setLayoutDirection(LAYOUT_DIRECTION_RTL);
+ textLayout.setBackgroundResource(R.drawable.bubble_stack_user_education_bg_rtl);
+ title.setGravity(Gravity.RIGHT);
+ description.setGravity(Gravity.RIGHT);
+ }
+ }
+
/**
* If necessary, hides the user education view for the bubble stack.
*
@@ -2515,6 +2550,10 @@ public class BubbleStackView extends FrameLayout
.spring(DynamicAnimation.SCALE_Y, 1f)
.spring(DynamicAnimation.TRANSLATION_X, targetX)
.spring(DynamicAnimation.TRANSLATION_Y, targetY)
+ .withEndActions(() -> {
+ View child = mManageMenu.getChildAt(0);
+ child.requestAccessibilityFocus();
+ })
.start();
mManageMenu.setVisibility(View.VISIBLE);
@@ -2758,16 +2797,28 @@ public class BubbleStackView extends FrameLayout
/**
* Logs the bubble UI event.
*
- * @param bubble the bubble that is being interacted on. Null value indicates that
- * the user interaction is not specific to one bubble.
+ * @param provider the bubble view provider that is being interacted on. Null value indicates
+ * that the user interaction is not specific to one bubble.
* @param action the user interaction enum.
*/
- private void logBubbleEvent(@Nullable BubbleViewProvider bubble, int action) {
- if (bubble == null) {
+ private void logBubbleEvent(@Nullable BubbleViewProvider provider, int action) {
+ if (provider == null || provider.getKey().equals(BubbleOverflow.KEY)) {
+ SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
+ mContext.getApplicationInfo().packageName,
+ provider == null ? null : BubbleOverflow.KEY /* notification channel */,
+ 0 /* notification ID */,
+ 0 /* bubble position */,
+ getBubbleCount(),
+ action,
+ getNormalizedXPosition(),
+ getNormalizedYPosition(),
+ false /* unread bubble */,
+ false /* on-going bubble */,
+ false /* isAppForeground (unused) */);
return;
}
- bubble.logUIEvent(getBubbleCount(), action, getNormalizedXPosition(),
- getNormalizedYPosition(), getBubbleIndex(bubble));
+ provider.logUIEvent(getBubbleCount(), action, getNormalizedXPosition(),
+ getNormalizedYPosition(), getBubbleIndex(provider));
}
/**
@@ -2806,20 +2857,4 @@ public class BubbleStackView extends FrameLayout
}
return bubbles;
}
-
- /**
- * Logs bubble UI click event.
- *
- * @param bubble the bubble notification entry that user is interacting with.
- * @param action the user interaction enum.
- */
- private void logBubbleClickEvent(Bubble bubble, int action) {
- bubble.logUIEvent(
- getBubbleCount(),
- action,
- getNormalizedXPosition(),
- getNormalizedYPosition(),
- getBubbleIndex(getExpandedBubble())
- );
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
index 525d5b56cc8e..1929fc4e9dbf 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
@@ -37,8 +37,6 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.AsyncTask;
import android.os.Parcelable;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.util.PathParser;
@@ -53,6 +51,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.lang.ref.WeakReference;
import java.util.List;
+import java.util.Objects;
/**
* Simple task to inflate views & load necessary info to display a bubble.
@@ -129,35 +128,10 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
@Nullable
static BubbleViewInfo populate(Context c, BubbleStackView stackView,
BubbleIconFactory iconFactory, Bubble b, boolean skipInflation) {
- final NotificationEntry entry = b.getEntry();
- if (entry == null) {
- // populate from ShortcutInfo when NotificationEntry is not available
- final ShortcutInfo s = b.getShortcutInfo();
- return populate(c, stackView, iconFactory, skipInflation || b.isInflated(),
- s.getPackage(), s.getUserHandle(), s, null);
- }
- final StatusBarNotification sbn = entry.getSbn();
- final String bubbleShortcutId = entry.getBubbleMetadata().getShortcutId();
- final ShortcutInfo si = bubbleShortcutId == null
- ? null : entry.getRanking().getShortcutInfo();
- return populate(
- c, stackView, iconFactory, skipInflation || b.isInflated(),
- sbn.getPackageName(), sbn.getUser(), si, entry);
- }
-
- private static BubbleViewInfo populate(
- @NonNull final Context c,
- @NonNull final BubbleStackView stackView,
- @NonNull final BubbleIconFactory iconFactory,
- final boolean isInflated,
- @NonNull final String packageName,
- @NonNull final UserHandle user,
- @Nullable final ShortcutInfo shortcutInfo,
- @Nullable final NotificationEntry entry) {
BubbleViewInfo info = new BubbleViewInfo();
// View inflation: only should do this once per bubble
- if (!isInflated) {
+ if (!skipInflation && !b.isInflated()) {
LayoutInflater inflater = LayoutInflater.from(c);
info.imageView = (BadgedImageView) inflater.inflate(
R.layout.bubble_view, stackView, false /* attachToRoot */);
@@ -167,8 +141,8 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
info.expandedView.setStackView(stackView);
}
- if (shortcutInfo != null) {
- info.shortcutInfo = shortcutInfo;
+ if (b.getShortcutInfo() != null) {
+ info.shortcutInfo = b.getShortcutInfo();
}
// App name & app icon
@@ -178,7 +152,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
Drawable appIcon;
try {
appInfo = pm.getApplicationInfo(
- packageName,
+ b.getPackageName(),
PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
@@ -186,23 +160,24 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
if (appInfo != null) {
info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
}
- appIcon = pm.getApplicationIcon(packageName);
- badgedIcon = pm.getUserBadgedIcon(appIcon, user);
+ appIcon = pm.getApplicationIcon(b.getPackageName());
+ badgedIcon = pm.getUserBadgedIcon(appIcon, b.getUser());
} catch (PackageManager.NameNotFoundException exception) {
// If we can't find package... don't think we should show the bubble.
- Log.w(TAG, "Unable to find package: " + packageName);
+ Log.w(TAG, "Unable to find package: " + b.getPackageName());
return null;
}
// Badged bubble image
Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo,
- entry == null ? null : entry.getBubbleMetadata());
+ b.getIcon());
if (bubbleDrawable == null) {
// Default to app icon
bubbleDrawable = appIcon;
}
- BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon);
+ BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon,
+ b.isImportantConversation());
info.badgedAppIcon = badgedIcon;
info.badgedBubbleImage = iconFactory.getBubbleBitmap(bubbleDrawable,
badgeBitmapInfo).icon;
@@ -222,8 +197,10 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
Color.WHITE, WHITE_SCRIM_ALPHA);
// Flyout
- if (entry != null) {
- info.flyoutMessage = extractFlyoutMessage(c, entry);
+ info.flyoutMessage = b.getFlyoutMessage();
+ if (info.flyoutMessage != null) {
+ info.flyoutMessage.senderAvatar =
+ loadSenderAvatar(c, info.flyoutMessage.senderIcon);
}
return info;
}
@@ -235,8 +212,8 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
* notification, based on its type. Returns null if there should not be an update message.
*/
@NonNull
- static Bubble.FlyoutMessage extractFlyoutMessage(Context context,
- NotificationEntry entry) {
+ static Bubble.FlyoutMessage extractFlyoutMessage(NotificationEntry entry) {
+ Objects.requireNonNull(entry);
final Notification underlyingNotif = entry.getSbn().getNotification();
final Class<? extends Notification.Style> style = underlyingNotif.getNotificationStyle();
@@ -264,20 +241,9 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
if (latestMessage != null) {
bubbleMessage.message = latestMessage.getText();
Person sender = latestMessage.getSenderPerson();
- bubbleMessage.senderName = sender != null
- ? sender.getName()
- : null;
-
+ bubbleMessage.senderName = sender != null ? sender.getName() : null;
bubbleMessage.senderAvatar = null;
- if (sender != null && sender.getIcon() != null) {
- if (sender.getIcon().getType() == Icon.TYPE_URI
- || sender.getIcon().getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
- context.grantUriPermission(context.getPackageName(),
- sender.getIcon().getUri(),
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- bubbleMessage.senderAvatar = sender.getIcon().loadDrawable(context);
- }
+ bubbleMessage.senderIcon = sender != null ? sender.getIcon() : null;
return bubbleMessage;
}
} else if (Notification.InboxStyle.class.equals(style)) {
@@ -306,4 +272,15 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
return bubbleMessage;
}
+
+ @Nullable
+ static Drawable loadSenderAvatar(@NonNull final Context context, @Nullable final Icon icon) {
+ Objects.requireNonNull(context);
+ if (icon == null) return null;
+ if (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
+ context.grantUriPermission(context.getPackageName(),
+ icon.getUri(), Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+ return icon.loadDrawable(context);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index cb8995a72dc3..8e232520a196 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -203,12 +203,22 @@ public class ExpandedAnimationController
public void updateResources(int orientation, Point displaySize) {
mScreenOrientation = orientation;
mDisplaySize = displaySize;
- if (mLayout != null) {
- Resources res = mLayout.getContext().getResources();
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
- mStatusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
+ if (mLayout == null) {
+ return;
}
+ Resources res = mLayout.getContext().getResources();
+ mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
+ mStatusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
+ mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
+ mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
+
+ // Includes overflow button.
+ float totalGapWidth = getWidthForDisplayingBubbles() - (mExpandedViewPadding * 2)
+ - (mBubblesMaxRendered + 1) * mBubbleSizePx;
+ mSpaceBetweenBubbles = totalGapWidth / mBubblesMaxRendered;
}
/**
@@ -464,18 +474,7 @@ public class ExpandedAnimationController
@Override
void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
- final Resources res = layout.getResources();
- mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
- mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
-
- // Includes overflow button.
- float totalGapWidth = getWidthForDisplayingBubbles() - (mExpandedViewPadding * 2)
- - (mBubblesMaxRendered + 1) * mBubbleSizePx;
- mSpaceBetweenBubbles = totalGapWidth / mBubblesMaxRendered;
+ updateResources(mScreenOrientation, mDisplaySize);
// Ensure that all child views are at 1x scale, and visible, in case they were animating
// in.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 3ef20444cb52..b378469c4c98 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -940,8 +940,12 @@ public class StackAnimationController extends
/** Returns the default stack position, which is on the top left. */
public PointF getDefaultStartPosition() {
- return new PointF(
- getAllowableStackPositionRegion().left,
+ boolean isRtl = mLayout != null
+ && mLayout.getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_RTL;
+ return new PointF(isRtl
+ ? getAllowableStackPositionRegion().right
+ : getAllowableStackPositionRegion().left,
getAllowableStackPositionRegion().top + mStackStartingVerticalOffset);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
index 355c4b115c8d..24768cd84a76 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
@@ -24,5 +24,6 @@ data class BubbleEntity(
val shortcutId: String,
val key: String,
val desiredHeight: Int,
- @DimenRes val desiredHeightResId: Int
+ @DimenRes val desiredHeightResId: Int,
+ val title: String? = null
)
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
index bdeb714b568c..894970f903ac 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
@@ -60,7 +60,8 @@ class BubbleVolatileRepository @Inject constructor(
// Verify the size of given bubbles is within capacity, otherwise trim down to capacity
val bubblesInRange = bubbles.takeLast(capacity)
// To ensure natural ordering of the bubbles, removes bubbles which already exist
- val uniqueBubbles = bubblesInRange.filterNot { entities.remove(it) }
+ val uniqueBubbles = bubblesInRange.filterNot { b: BubbleEntity ->
+ entities.removeIf { e: BubbleEntity -> b.key == e.key } }
val overflowCount = entities.size + bubblesInRange.size - capacity
if (overflowCount > 0) {
// Uncache ShortcutInfo of bubbles that will be removed due to capacity
@@ -72,7 +73,9 @@ class BubbleVolatileRepository @Inject constructor(
}
@Synchronized
- fun removeBubbles(bubbles: List<BubbleEntity>) = uncache(bubbles.filter { entities.remove(it) })
+ fun removeBubbles(bubbles: List<BubbleEntity>) =
+ uncache(bubbles.filter { b: BubbleEntity ->
+ entities.removeIf { e: BubbleEntity -> b.key == e.key } })
private fun cache(bubbles: List<BubbleEntity>) {
bubbles.groupBy { ShortcutKey(it.userId, it.packageName) }.forEach { (key, bubbles) ->
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
index a8faf258da07..bf163a230aff 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
@@ -25,7 +25,11 @@ import java.io.InputStream
import java.io.OutputStream
import java.nio.charset.StandardCharsets
+// TODO: handle version changes gracefully
+private const val CURRENT_VERSION = 1
+
private const val TAG_BUBBLES = "bs"
+private const val ATTR_VERSION = "v"
private const val TAG_BUBBLE = "bb"
private const val ATTR_USER_ID = "uid"
private const val ATTR_PACKAGE = "pkg"
@@ -33,6 +37,7 @@ private const val ATTR_SHORTCUT_ID = "sid"
private const val ATTR_KEY = "key"
private const val ATTR_DESIRED_HEIGHT = "h"
private const val ATTR_DESIRED_HEIGHT_RES_ID = "hid"
+private const val ATTR_TITLE = "t"
/**
* Writes the bubbles in xml format into given output stream.
@@ -43,6 +48,7 @@ fun writeXml(stream: OutputStream, bubbles: List<BubbleEntity>) {
serializer.setOutput(stream, StandardCharsets.UTF_8.name())
serializer.startDocument(null, true)
serializer.startTag(null, TAG_BUBBLES)
+ serializer.attribute(null, ATTR_VERSION, CURRENT_VERSION.toString())
bubbles.forEach { b -> writeXmlEntry(serializer, b) }
serializer.endTag(null, TAG_BUBBLES)
serializer.endDocument()
@@ -63,6 +69,7 @@ private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) {
serializer.attribute(null, ATTR_KEY, bubble.key)
serializer.attribute(null, ATTR_DESIRED_HEIGHT, bubble.desiredHeight.toString())
serializer.attribute(null, ATTR_DESIRED_HEIGHT_RES_ID, bubble.desiredHeightResId.toString())
+ bubble.title?.let { serializer.attribute(null, ATTR_TITLE, it) }
serializer.endTag(null, TAG_BUBBLE)
} catch (e: IOException) {
throw RuntimeException(e)
@@ -77,9 +84,12 @@ fun readXml(stream: InputStream): List<BubbleEntity> {
val parser: XmlPullParser = Xml.newPullParser()
parser.setInput(stream, StandardCharsets.UTF_8.name())
XmlUtils.beginDocument(parser, TAG_BUBBLES)
- val outerDepth = parser.depth
- while (XmlUtils.nextElementWithin(parser, outerDepth)) {
- bubbles.add(readXmlEntry(parser) ?: continue)
+ val version = parser.getAttributeWithName(ATTR_VERSION)?.toInt()
+ if (version != null && version == CURRENT_VERSION) {
+ val outerDepth = parser.depth
+ while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+ bubbles.add(readXmlEntry(parser) ?: continue)
+ }
}
return bubbles
}
@@ -92,7 +102,8 @@ private fun readXmlEntry(parser: XmlPullParser): BubbleEntity? {
parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null,
parser.getAttributeWithName(ATTR_KEY) ?: return null,
parser.getAttributeWithName(ATTR_DESIRED_HEIGHT)?.toInt() ?: return null,
- parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null
+ parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null,
+ parser.getAttributeWithName(ATTR_TITLE)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
index d4d4d2a7d8fe..eed55315e836 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
@@ -20,7 +20,7 @@ import android.content.ComponentName
import android.service.controls.Control
import android.service.controls.ControlsProviderService
import android.service.controls.actions.ControlAction
-import com.android.systemui.controls.UserAwareController
+import com.android.systemui.util.UserAwareController
import java.util.function.Consumer
/**
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 45ba1e6012fe..496741b1cd6f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -21,7 +21,7 @@ import android.service.controls.Control
import android.service.controls.ControlsProviderService
import android.service.controls.actions.ControlAction
import com.android.systemui.controls.ControlStatus
-import com.android.systemui.controls.UserAwareController
+import com.android.systemui.util.UserAwareController
import com.android.systemui.controls.management.ControlsFavoritingActivity
import com.android.systemui.controls.ui.ControlsUiController
import java.util.function.Consumer
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
index 647daccca8bd..b9f16665944f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
@@ -18,7 +18,7 @@ package com.android.systemui.controls.management
import android.content.ComponentName
import com.android.systemui.controls.ControlsServiceInfo
-import com.android.systemui.controls.UserAwareController
+import com.android.systemui.util.UserAwareController
import com.android.systemui.statusbar.policy.CallbackController
/**
@@ -26,7 +26,7 @@ import com.android.systemui.statusbar.policy.CallbackController
*/
interface ControlsListingController :
CallbackController<ControlsListingController.ControlsListingCallback>,
- UserAwareController {
+ UserAwareController {
/**
* @return the current list of services that satisfies the [ServiceListing].
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index d2501fa8a66b..c073642afa4e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -35,7 +35,6 @@ import com.android.systemui.globalactions.GlobalActionsComponent
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.R
import javax.inject.Inject
import javax.inject.Singleton
@@ -164,8 +163,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
it.show()
}
} else {
- cvh.setTransientStatus(
- cvh.context.resources.getString(R.string.controls_error_failed))
+ cvh.setErrorStatus()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index e8530272a5c8..865a38a2076c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -67,7 +67,6 @@ class ControlViewHolder(
companion object {
const val STATE_ANIMATION_DURATION = 700L
- private const val UPDATE_DELAY_IN_MILLIS = 3000L
private const val ALPHA_ENABLED = 255
private const val ALPHA_DISABLED = 0
private const val STATUS_ALPHA_ENABLED = 1f
@@ -113,7 +112,6 @@ class ControlViewHolder(
val context: Context = layout.getContext()
val clipLayer: ClipDrawable
lateinit var cws: ControlWithState
- var cancelUpdate: Runnable? = null
var behavior: Behavior? = null
var lastAction: ControlAction? = null
var isLoading = false
@@ -128,6 +126,8 @@ class ControlViewHolder(
val controlTemplate: ControlTemplate
get() = cws.control?.let { it.controlTemplate } ?: ControlTemplate.NO_TEMPLATE
+ var userInteractionInProgress = false
+
init {
val ld = layout.getBackground() as LayerDrawable
ld.mutate()
@@ -139,9 +139,12 @@ class ControlViewHolder(
}
fun bindData(cws: ControlWithState) {
- this.cws = cws
+ // If an interaction is in progress, the update may visually interfere with the action the
+ // action the user wants to make. Don't apply the update, and instead assume a new update
+ // will coming from when the user interaction is complete.
+ if (userInteractionInProgress) return
- cancelUpdate?.run()
+ this.cws = cws
// For the following statuses only, assume the title/subtitle could not be set properly
// by the app and instead use the last known information from favorites
@@ -181,20 +184,20 @@ class ControlViewHolder(
lastChallengeDialog = null
ControlAction.RESPONSE_UNKNOWN -> {
lastChallengeDialog = null
- setTransientStatus(context.resources.getString(R.string.controls_error_failed))
+ setErrorStatus()
}
ControlAction.RESPONSE_FAIL -> {
lastChallengeDialog = null
- setTransientStatus(context.resources.getString(R.string.controls_error_failed))
+ setErrorStatus()
}
ControlAction.RESPONSE_CHALLENGE_PIN -> {
lastChallengeDialog = ChallengeDialogs.createPinDialog(
- this, false, failedAttempt, onDialogCancel)
+ this, false /* useAlphanumeric */, failedAttempt, onDialogCancel)
lastChallengeDialog?.show()
}
ControlAction.RESPONSE_CHALLENGE_PASSPHRASE -> {
lastChallengeDialog = ChallengeDialogs.createPinDialog(
- this, false, failedAttempt, onDialogCancel)
+ this, true /* useAlphanumeric */, failedAttempt, onDialogCancel)
lastChallengeDialog?.show()
}
ControlAction.RESPONSE_CHALLENGE_ACK -> {
@@ -212,19 +215,10 @@ class ControlViewHolder(
visibleDialog = null
}
- fun setTransientStatus(tempStatus: String) {
- val previousText = status.getText()
-
- cancelUpdate = uiExecutor.executeDelayed({
- animateStatusChange(/* animated */ true, {
- setStatusText(previousText, /* immediately */ true)
- updateContentDescription()
- })
- }, UPDATE_DELAY_IN_MILLIS)
-
+ fun setErrorStatus() {
+ val text = context.resources.getString(R.string.controls_error_failed)
animateStatusChange(/* animated */ true, {
- setStatusText(tempStatus, /* immediately */ true)
- updateContentDescription()
+ setStatusText(text, /* immediately */ true)
})
}
@@ -296,6 +290,7 @@ class ControlViewHolder(
if (immediately) {
status.alpha = STATUS_ALPHA_ENABLED
status.text = text
+ updateContentDescription()
}
nextStatusText = text
}
@@ -412,6 +407,8 @@ class ControlViewHolder(
setEnabled(enabled)
status.text = text
+ updateContentDescription()
+
status.setTextColor(color)
control?.getCustomIcon()?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
index dac55378daca..116f3ca898c0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
@@ -77,8 +77,7 @@ class StatusBehavior : Behavior {
cws.control?.getAppIntent()?.send()
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
} catch (e: PendingIntent.CanceledException) {
- cvh.setTransientStatus(
- cvh.context.resources.getString(R.string.controls_error_failed))
+ cvh.setErrorStatus()
}
dialog.dismiss()
})
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index 02f80e842516..aa11df41a7b7 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -163,8 +163,10 @@ class ToggleRangeBehavior : Behavior {
AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_FLOAT
}
- val rangeInfo = AccessibilityNodeInfo.RangeInfo.obtain(type, min, max, current)
- info.setRangeInfo(rangeInfo)
+ if (isChecked) {
+ val rangeInfo = AccessibilityNodeInfo.RangeInfo.obtain(type, min, max, current)
+ info.setRangeInfo(rangeInfo)
+ }
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_PROGRESS)
}
@@ -214,6 +216,7 @@ class ToggleRangeBehavior : Behavior {
}
fun beginUpdateRange() {
+ cvh.userInteractionInProgress = true
cvh.setStatusTextSize(context.getResources()
.getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
}
@@ -294,6 +297,7 @@ class ToggleRangeBehavior : Behavior {
cvh.setStatusText("$currentStatusText $currentRangeValue", /* immediately */ true)
cvh.controlActionCoordinator.setValue(cvh, rangeTemplate.getTemplateId(),
findNearestStep(levelToRangeValue(clipLayer.getLevel())))
+ cvh.userInteractionInProgress = false
}
fun findNearestStep(value: Float): Float {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 1f30305ab169..fedc9e31a4ec 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -61,6 +61,8 @@ import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.util.leak.LeakDetector;
+import java.util.concurrent.Executor;
+
import javax.inject.Named;
import javax.inject.Singleton;
@@ -188,11 +190,12 @@ public class DependencyProvider {
public BroadcastDispatcher providesBroadcastDispatcher(
Context context,
@Background Looper backgroundLooper,
+ @Background Executor backgroundExecutor,
DumpManager dumpManager,
BroadcastDispatcherLogger logger
) {
- BroadcastDispatcher bD =
- new BroadcastDispatcher(context, backgroundLooper, dumpManager, logger);
+ BroadcastDispatcher bD = new BroadcastDispatcher(context, backgroundLooper,
+ backgroundExecutor, dumpManager, logger);
bD.initialize();
return bD;
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 915092134cc5..c891bf6cb53c 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -22,6 +22,7 @@ import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
+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_USER_LOCKDOWN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
@@ -395,11 +396,14 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
controlsComponent.getControlsListingController().get()
.addCallback(list -> {
mControlsServiceInfos = list;
- // This callback may occur after the dialog has been shown.
- // If so, add controls into the already visible space
- if (mDialog != null && !mDialog.isShowingControls()
- && shouldShowControls()) {
- mDialog.showControls(mControlsUiControllerOptional.get());
+ // This callback may occur after the dialog has been shown. If so, add
+ // controls into the already visible space or show the lock msg if needed.
+ if (mDialog != null) {
+ if (!mDialog.isShowingControls() && shouldShowControls()) {
+ mDialog.showControls(mControlsUiControllerOptional.get());
+ } else if (shouldShowLockMessage()) {
+ mDialog.showLockMessage();
+ }
}
});
}
@@ -700,9 +704,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mStatusBarService, mNotificationShadeWindowController,
controlsAvailable(), uiController,
mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter);
- boolean walletViewAvailable = walletViewController != null
- && walletViewController.getPanelContent() != null;
- if (shouldShowLockMessage(walletViewAvailable)) {
+
+ if (shouldShowLockMessage()) {
dialog.showLockMessage();
}
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
@@ -1422,16 +1425,26 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
Log.w(TAG, "No power options action found at position: " + position);
return null;
}
- int viewLayoutResource = com.android.systemui.R.layout.controls_more_item;
+ int viewLayoutResource = com.android.systemui.R.layout.global_actions_power_item;
View view = convertView != null ? convertView
: LayoutInflater.from(mContext).inflate(viewLayoutResource, parent, false);
- TextView textView = (TextView) view;
- if (action.getMessageResId() != 0) {
- textView.setText(action.getMessageResId());
+ view.setOnClickListener(v -> onClickItem(position));
+ if (action instanceof LongPressAction) {
+ view.setOnLongClickListener(v -> onLongClickItem(position));
+ }
+ ImageView icon = view.findViewById(R.id.icon);
+ TextView messageView = view.findViewById(R.id.message);
+ messageView.setSelected(true); // necessary for marquee to work
+
+ icon.setImageDrawable(action.getIcon(mContext));
+ icon.setScaleType(ScaleType.CENTER_CROP);
+
+ if (action.getMessage() != null) {
+ messageView.setText(action.getMessage());
} else {
- textView.setText(action.getMessage());
+ messageView.setText(action.getMessageResId());
}
- return textView;
+ return view;
}
private boolean onLongClickItem(int position) {
@@ -1567,6 +1580,11 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
int getMessageResId();
/**
+ * Return the icon drawable for this action.
+ */
+ Drawable getIcon(Context context);
+
+ /**
* Return the message associated with this action, or null if it doesn't have one.
* @return
*/
@@ -1630,6 +1648,15 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return mMessage;
}
+ @Override
+ public Drawable getIcon(Context context) {
+ if (mIcon != null) {
+ return mIcon;
+ } else {
+ return context.getDrawable(mIconResId);
+ }
+ }
+
public View create(
Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
View v = inflater.inflate(com.android.systemui.R.layout.global_actions_grid_item_v2,
@@ -1639,12 +1666,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
TextView messageView = v.findViewById(R.id.message);
messageView.setSelected(true); // necessary for marquee to work
- if (mIcon != null) {
- icon.setImageDrawable(mIcon);
- icon.setScaleType(ScaleType.CENTER_CROP);
- } else if (mIconResId != 0) {
- icon.setImageDrawable(context.getDrawable(mIconResId));
- }
+ icon.setImageDrawable(getIcon(context));
+ icon.setScaleType(ScaleType.CENTER_CROP);
+
if (mMessage != null) {
messageView.setText(mMessage);
} else {
@@ -1735,6 +1759,11 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return isOn() ? mEnabledIconResId : mDisabledIconResid;
}
+ @Override
+ public Drawable getIcon(Context context) {
+ return context.getDrawable(getIconResId());
+ }
+
public View create(Context context, View convertView, ViewGroup parent,
LayoutInflater inflater) {
willCreate();
@@ -1901,6 +1930,12 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return null;
}
+ @Override
+ public Drawable getIcon(Context context) {
+ return null;
+ }
+
+
public View create(Context context, View convertView, ViewGroup parent,
LayoutInflater inflater) {
View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false);
@@ -2072,7 +2107,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private final NotificationShadeDepthController mDepthController;
private final SysUiState mSysUiState;
private ListPopupWindow mOverflowPopup;
- private ListPopupWindow mPowerOptionsPopup;
+ private Dialog mPowerOptionsDialog;
private final Runnable mOnRotateCallback;
private final boolean mControlsAvailable;
@@ -2208,21 +2243,6 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
}
- private ListPopupWindow createPowerOptionsPopup() {
- GlobalActionsPopupMenu popup = new GlobalActionsPopupMenu(
- new ContextThemeWrapper(
- mContext,
- com.android.systemui.R.style.Control_ListPopupWindow
- ), false /* isDropDownMode */);
- popup.setOnItemClickListener(
- (parent, view, position, id) -> mPowerOptionsAdapter.onClickItem(position));
- popup.setOnItemLongClickListener(
- (parent, view, position, id) -> mPowerOptionsAdapter.onLongClickItem(position));
- popup.setAnchorView(mGlobalActionsLayout);
- popup.setAdapter(mPowerOptionsAdapter);
- return popup;
- }
-
private ListPopupWindow createPowerOverflowPopup() {
GlobalActionsPopupMenu popup = new GlobalActionsPopupMenu(
new ContextThemeWrapper(
@@ -2241,8 +2261,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
public void showPowerOptionsMenu() {
- mPowerOptionsPopup = createPowerOptionsPopup();
- mPowerOptionsPopup.show();
+ mPowerOptionsDialog = GlobalActionsPowerDialog.create(mContext, mPowerOptionsAdapter);
+ mPowerOptionsDialog.show();
}
private void showPowerOverflowMenu() {
@@ -2476,11 +2496,11 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
private void dismissPowerOptions(boolean immediate) {
- if (mPowerOptionsPopup != null) {
+ if (mPowerOptionsDialog != null) {
if (immediate) {
- mPowerOptionsPopup.dismissImmediate();
+ mPowerOptionsDialog.dismiss();
} else {
- mPowerOptionsPopup.dismiss();
+ mPowerOptionsDialog.dismiss();
}
}
}
@@ -2591,7 +2611,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private boolean shouldShowControls() {
return (mKeyguardStateController.isUnlocked() || mShowLockScreenCardsAndControls)
- && controlsAvailable();
+ && controlsAvailable()
+ && mLockPatternUtils.getStrongAuthForUser(getCurrentUser().id)
+ != STRONG_AUTH_REQUIRED_AFTER_BOOT;
}
private boolean controlsAvailable() {
@@ -2601,10 +2623,18 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
&& !mControlsServiceInfos.isEmpty();
}
- private boolean shouldShowLockMessage(boolean walletViewAvailable) {
+ private boolean walletViewAvailable() {
+ GlobalActionsPanelPlugin.PanelViewController walletViewController =
+ getWalletViewController();
+ return walletViewController != null && walletViewController.getPanelContent() != null;
+ }
+
+ private boolean shouldShowLockMessage() {
+ boolean isLockedAfterBoot = mLockPatternUtils.getStrongAuthForUser(getCurrentUser().id)
+ == STRONG_AUTH_REQUIRED_AFTER_BOOT;
return !mKeyguardStateController.isUnlocked()
- && !mShowLockScreenCardsAndControls
- && (controlsAvailable() || walletViewAvailable);
+ && (!mShowLockScreenCardsAndControls || isLockedAfterBoot)
+ && (controlsAvailable() || walletViewAvailable());
}
private void onPowerMenuLockScreenSettingsChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPowerDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPowerDialog.java
new file mode 100644
index 000000000000..9dec3ab859b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPowerDialog.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.globalactions;
+
+import android.annotation.NonNull;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ListAdapter;
+
+/**
+ * Creates a customized Dialog for displaying the Shut Down and Restart actions.
+ */
+public class GlobalActionsPowerDialog {
+
+ /**
+ * Create a dialog for displaying Shut Down and Restart actions.
+ */
+ public static Dialog create(@NonNull Context context, ListAdapter adapter) {
+ ViewGroup listView = (ViewGroup) LayoutInflater.from(context).inflate(
+ com.android.systemui.R.layout.global_actions_power_dialog, null);
+
+ for (int i = 0; i < adapter.getCount(); i++) {
+ View action = adapter.getView(i, null, listView);
+ listView.addView(action);
+ }
+
+ Resources res = context.getResources();
+
+ Dialog dialog = new Dialog(context);
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ dialog.setContentView(listView);
+
+ Window window = dialog.getWindow();
+ window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+ window.setTitle(""); // prevent Talkback from speaking first item name twice
+ window.setBackgroundDrawable(res.getDrawable(
+ com.android.systemui.R.drawable.control_background, context.getTheme()));
+
+ return dialog;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 2df0507a8864..d5c92f26e12b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -20,9 +20,8 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
@@ -33,6 +32,7 @@ import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.util.Log;
import android.view.View;
+import android.view.ViewOutlineProvider;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@@ -41,8 +41,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.constraintlayout.widget.ConstraintSet;
-import androidx.core.graphics.drawable.RoundedBitmapDrawable;
-import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.android.settingslib.Utils;
import com.android.settingslib.media.MediaOutputSliceConstants;
@@ -52,8 +50,6 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.util.animation.TransitionLayout;
-import org.jetbrains.annotations.NotNull;
-
import java.util.List;
import java.util.concurrent.Executor;
@@ -87,6 +83,8 @@ public class MediaControlPanel {
private int mBackgroundColor;
private int mAlbumArtSize;
private int mAlbumArtRadius;
+ // This will provide the corners for the album art.
+ private final ViewOutlineProvider mViewOutlineProvider;
/**
* Initialize a new control panel
@@ -104,6 +102,13 @@ public class MediaControlPanel {
mSeekBarViewModel = seekBarViewModel;
mMediaViewController = mediaViewController;
loadDimens();
+
+ mViewOutlineProvider = new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(0, 0, mAlbumArtSize, mAlbumArtSize, mAlbumArtRadius);
+ }
+ };
}
public void onDestroy() {
@@ -162,6 +167,11 @@ public class MediaControlPanel {
public void attach(PlayerViewHolder vh) {
mViewHolder = vh;
TransitionLayout player = vh.getPlayer();
+
+ ImageView albumView = vh.getAlbumView();
+ albumView.setOutlineProvider(mViewOutlineProvider);
+ albumView.setClipToOutline(true);
+
mSeekBarObserver = new SeekBarObserver(vh);
mSeekBarViewModel.getProgress().observeForever(mSeekBarObserver);
mSeekBarViewModel.attachTouchHandlers(vh.getSeekBar());
@@ -171,7 +181,7 @@ public class MediaControlPanel {
/**
* Bind this view based on the data given
*/
- public void bind(@NotNull MediaData data) {
+ public void bind(@NonNull MediaData data) {
if (mViewHolder == null) {
return;
}
@@ -202,11 +212,9 @@ public class MediaControlPanel {
}
ImageView albumView = mViewHolder.getAlbumView();
- // TODO: migrate this to a view with rounded corners instead of baking the rounding
- // into the bitmap
boolean hasArtwork = data.getArtwork() != null;
if (hasArtwork) {
- Drawable artwork = createRoundedBitmap(data.getArtwork());
+ Drawable artwork = scaleDrawable(data.getArtwork());
albumView.setImageDrawable(artwork);
}
setVisibleAndAlpha(collapsedSet, R.id.album_art, hasArtwork);
@@ -334,7 +342,7 @@ public class MediaControlPanel {
}
@UiThread
- private Drawable createRoundedBitmap(Icon icon) {
+ private Drawable scaleDrawable(Icon icon) {
if (icon == null) {
return null;
}
@@ -355,14 +363,7 @@ public class MediaControlPanel {
bounds.offset((int) -offsetX,(int) -offsetY);
}
drawable.setBounds(bounds);
- Bitmap scaled = Bitmap.createBitmap(mAlbumArtSize, mAlbumArtSize,
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(scaled);
- drawable.draw(canvas);
- RoundedBitmapDrawable artwork = RoundedBitmapDrawableFactory.create(
- mContext.getResources(), scaled);
- artwork.setCornerRadius(mAlbumArtRadius);
- return artwork;
+ return drawable;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 5300795189de..1ec285a8f561 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -38,18 +38,20 @@ import android.service.notification.StatusBarNotification
import android.text.TextUtils
import android.util.Log
import com.android.internal.graphics.ColorUtils
+import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
-import com.android.systemui.statusbar.notification.NotificationEntryManager
-import com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON
import com.android.systemui.statusbar.notification.row.HybridGroupManager
import com.android.systemui.util.Assert
import com.android.systemui.util.Utils
+import java.io.FileDescriptor
import java.io.IOException
+import java.io.PrintWriter
import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Singleton
@@ -85,20 +87,35 @@ fun isMediaNotification(sbn: StatusBarNotification): Boolean {
* A class that facilitates management and loading of Media Data, ready for binding.
*/
@Singleton
-class MediaDataManager @Inject constructor(
+class MediaDataManager(
private val context: Context,
- private val mediaControllerFactory: MediaControllerFactory,
- private val notificationEntryManager: NotificationEntryManager,
@Background private val backgroundExecutor: Executor,
@Main private val foregroundExecutor: Executor,
- broadcastDispatcher: BroadcastDispatcher,
+ private val mediaControllerFactory: MediaControllerFactory,
+ private val broadcastDispatcher: BroadcastDispatcher,
+ dumpManager: DumpManager,
mediaTimeoutListener: MediaTimeoutListener,
- mediaResumeListener: MediaResumeListener
-) {
+ mediaResumeListener: MediaResumeListener,
+ private val useMediaResumption: Boolean,
+ private val useQsMediaPlayer: Boolean
+) : Dumpable {
private val listeners: MutableSet<Listener> = mutableSetOf()
private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
- private val useMediaResumption: Boolean = Utils.useMediaResumption(context)
+
+ @Inject
+ constructor(
+ context: Context,
+ @Background backgroundExecutor: Executor,
+ @Main foregroundExecutor: Executor,
+ mediaControllerFactory: MediaControllerFactory,
+ dumpManager: DumpManager,
+ broadcastDispatcher: BroadcastDispatcher,
+ mediaTimeoutListener: MediaTimeoutListener,
+ mediaResumeListener: MediaResumeListener
+ ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory,
+ broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener,
+ Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context))
private val userChangeReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -128,6 +145,7 @@ class MediaDataManager @Inject constructor(
}
init {
+ dumpManager.registerDumpable(TAG, this)
mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean ->
setTimedOut(token, timedOut) }
addListener(mediaTimeoutListener)
@@ -159,8 +177,13 @@ class MediaDataManager @Inject constructor(
context.registerReceiver(appChangeReceiver, uninstallFilter)
}
+ fun destroy() {
+ context.unregisterReceiver(appChangeReceiver)
+ broadcastDispatcher.unregisterReceiver(userChangeReceiver)
+ }
+
fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
- if (Utils.useQsMediaPlayer(context) && isMediaNotification(sbn)) {
+ if (useQsMediaPlayer && isMediaNotification(sbn)) {
Assert.isMainThread()
val oldKey = findExistingEntry(key, sbn.packageName)
if (oldKey == null) {
@@ -253,18 +276,18 @@ class MediaDataManager @Inject constructor(
*/
fun removeListener(listener: Listener) = listeners.remove(listener)
+ /**
+ * Called whenever the player has been paused or stopped for a while.
+ * This will make the player not active anymore, hiding it from QQS and Keyguard.
+ * @see MediaData.active
+ */
private fun setTimedOut(token: String, timedOut: Boolean) {
mediaEntries[token]?.let {
- if (Utils.useMediaResumption(context)) {
- if (it.active == !timedOut) {
- return
- }
- it.active = !timedOut
- onMediaDataLoaded(token, token, it)
- } else if (timedOut) {
- notificationEntryManager.removeNotification(it.notificationKey, null /* ranking */,
- UNDEFINED_DISMISS_REASON)
+ if (it.active == !timedOut) {
+ return
}
+ it.active = !timedOut
+ onMediaDataLoaded(token, token, it)
}
}
@@ -293,10 +316,11 @@ class MediaDataManager @Inject constructor(
} else {
null
}
+ val bgColor = artworkBitmap?.let { computeBackgroundColor(it) } ?: Color.DKGRAY
val mediaAction = getResumeMediaAction(resumeAction)
foregroundExecutor.execute {
- onMediaDataLoaded(packageName, null, MediaData(true, Color.DKGRAY, appName,
+ onMediaDataLoaded(packageName, null, MediaData(true, bgColor, appName,
null, desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(0),
packageName, token, appIntent, device = null, active = false,
resumeAction = resumeAction))
@@ -319,7 +343,6 @@ class MediaDataManager @Inject constructor(
// Foreground and Background colors computed from album art
val notif: Notification = sbn.notification
- var bgColor = Color.WHITE
var artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ART)
if (artworkBitmap == null) {
artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART)
@@ -349,26 +372,8 @@ class MediaDataManager @Inject constructor(
drawable.draw(canvas)
}
}
- val p = MediaNotificationProcessor.generateArtworkPaletteBuilder(artworkBitmap)
- .generate()
- val swatch = MediaNotificationProcessor.findBackgroundSwatch(p)
- bgColor = swatch.rgb
- }
- // Adapt background color, so it's always subdued and text is legible
- val tmpHsl = floatArrayOf(0f, 0f, 0f)
- ColorUtils.colorToHSL(bgColor, tmpHsl)
-
- val l = tmpHsl[2]
- // Colors with very low luminosity can have any saturation. This means that changing the
- // luminosity can make a black become red. Let's remove the saturation of very light or
- // very dark colors to avoid this issue.
- if (l < LUMINOSITY_THRESHOLD || l > 1f - LUMINOSITY_THRESHOLD) {
- tmpHsl[1] = 0f
}
- tmpHsl[1] *= SATURATION_MULTIPLIER
- tmpHsl[2] = DEFAULT_LUMINOSITY
-
- bgColor = ColorUtils.HSLToColor(tmpHsl)
+ val bgColor = computeBackgroundColor(artworkBitmap)
// App name
val builder = Notification.Builder.recoverBuilder(context, notif)
@@ -480,6 +485,33 @@ class MediaDataManager @Inject constructor(
}
}
+ private fun computeBackgroundColor(artworkBitmap: Bitmap?): Int {
+ var color = Color.WHITE
+ if (artworkBitmap != null) {
+ // If we have art, get colors from that
+ val p = MediaNotificationProcessor.generateArtworkPaletteBuilder(artworkBitmap)
+ .generate()
+ val swatch = MediaNotificationProcessor.findBackgroundSwatch(p)
+ color = swatch.rgb
+ }
+ // Adapt background color, so it's always subdued and text is legible
+ val tmpHsl = floatArrayOf(0f, 0f, 0f)
+ ColorUtils.colorToHSL(color, tmpHsl)
+
+ val l = tmpHsl[2]
+ // Colors with very low luminosity can have any saturation. This means that changing the
+ // luminosity can make a black become red. Let's remove the saturation of very light or
+ // very dark colors to avoid this issue.
+ if (l < LUMINOSITY_THRESHOLD || l > 1f - LUMINOSITY_THRESHOLD) {
+ tmpHsl[1] = 0f
+ }
+ tmpHsl[1] *= SATURATION_MULTIPLIER
+ tmpHsl[2] = DEFAULT_LUMINOSITY
+
+ color = ColorUtils.HSLToColor(tmpHsl)
+ return color
+ }
+
private fun getResumeMediaAction(action: Runnable): MediaAction {
return MediaAction(
context.getDrawable(R.drawable.lb_ic_play),
@@ -561,4 +593,12 @@ class MediaDataManager @Inject constructor(
*/
fun onMediaDataRemoved(key: String) {}
}
+
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.apply {
+ println("listeners: $listeners")
+ println("mediaEntries: $mediaEntries")
+ println("useMediaResumption: $useMediaResumption")
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index b86e1d0503d4..26fa29613dc4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -193,6 +193,8 @@ class MediaHierarchyManager @Inject constructor(
override fun onDozingChanged(isDozing: Boolean) {
if (!isDozing) {
dozeAnimationRunning = false
+ } else {
+ updateDesiredLocation()
}
}
})
@@ -510,12 +512,19 @@ class MediaHierarchyManager @Inject constructor(
(statusbarState == StatusBarState.KEYGUARD ||
statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER))
val allowedOnLockscreen = notifLockscreenUserManager.shouldShowLockscreenNotifications()
- return when {
+ val location = when {
qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
else -> LOCATION_QQS
}
+ // When we're on lock screen and the player is not active, we should keep it in QS.
+ // Otherwise it will try to animate a transition that doesn't make sense.
+ if (location == LOCATION_LOCKSCREEN && getHost(location)?.visible != true &&
+ !statusBarStateController.isDozing) {
+ return LOCATION_QS
+ }
+ return location
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
index 9b9a6b4b13ab..bccc3abd8a27 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
@@ -13,6 +13,7 @@ import androidx.core.view.GestureDetectorCompat
import com.android.systemui.R
import com.android.systemui.qs.PageIndicator
import com.android.systemui.statusbar.notification.VisualStabilityManager
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.animation.requiresRemeasuring
import javax.inject.Inject
@@ -31,7 +32,8 @@ class MediaViewManager @Inject constructor(
private val mediaControlPanelFactory: Provider<MediaControlPanel>,
private val visualStabilityManager: VisualStabilityManager,
private val mediaHostStatesManager: MediaHostStatesManager,
- mediaManager: MediaDataCombineLatest
+ mediaManager: MediaDataCombineLatest,
+ configurationController: ConfigurationController
) {
/**
@@ -74,6 +76,7 @@ class MediaViewManager @Inject constructor(
private val mediaCarousel: HorizontalScrollView
val mediaFrame: ViewGroup
val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
+ private val mediaData: MutableMap<String, MediaData> = mutableMapOf()
private val mediaContent: ViewGroup
private val pageIndicator: PageIndicator
private val gestureDetector: GestureDetectorCompat
@@ -120,6 +123,11 @@ class MediaViewManager @Inject constructor(
return this@MediaViewManager.onTouch(view, motionEvent)
}
}
+ private val configListener = object : ConfigurationController.ConfigurationListener {
+ override fun onDensityOrFontScaleChanged() {
+ recreatePlayers()
+ }
+ }
init {
gestureDetector = GestureDetectorCompat(context, gestureListener)
@@ -130,6 +138,7 @@ class MediaViewManager @Inject constructor(
mediaCarousel.setOnTouchListener(touchListener)
mediaCarousel.setOverScrollMode(View.OVER_SCROLL_NEVER)
mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
+ configurationController.addCallback(configListener)
visualStabilityCallback = VisualStabilityManager.Callback {
if (needsReordering) {
needsReordering = false
@@ -142,29 +151,14 @@ class MediaViewManager @Inject constructor(
true /* persistent */)
mediaManager.addListener(object : MediaDataManager.Listener {
override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
- updateView(key, oldKey, data)
- updatePlayerVisibilities()
- mediaCarousel.requiresRemeasuring = true
+ oldKey?.let { mediaData.remove(it) }
+ mediaData.put(key, data)
+ addOrUpdatePlayer(key, oldKey, data)
}
override fun onMediaDataRemoved(key: String) {
- val removed = mediaPlayers.remove(key)
- removed?.apply {
- val beforeActive = mediaContent.indexOfChild(removed.view?.player) <=
- activeMediaIndex
- mediaContent.removeView(removed.view?.player)
- removed.onDestroy()
- updateMediaPaddings()
- if (beforeActive) {
- // also update the index here since the scroll below might not always lead
- // to a scrolling changed
- activeMediaIndex = Math.max(0, activeMediaIndex - 1)
- mediaCarousel.scrollX = Math.max(mediaCarousel.scrollX -
- playerWidthPlusPadding, 0)
- }
- updatePlayerVisibilities()
- updatePageIndicator()
- }
+ mediaData.remove(key)
+ removePlayer(key)
}
})
mediaHostStatesManager.addCallback(object : MediaHostStatesManager.Callback {
@@ -253,7 +247,7 @@ class MediaViewManager @Inject constructor(
}
}
- private fun updateView(key: String, oldKey: String?, data: MediaData) {
+ private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData) {
// If the key was changed, update entry
val oldData = mediaPlayers[oldKey]
if (oldData != null) {
@@ -288,6 +282,39 @@ class MediaViewManager @Inject constructor(
existingPlayer?.bind(data)
updateMediaPaddings()
updatePageIndicator()
+ updatePlayerVisibilities()
+ mediaCarousel.requiresRemeasuring = true
+ }
+
+ private fun removePlayer(key: String) {
+ val removed = mediaPlayers.remove(key)
+ removed?.apply {
+ val beforeActive = mediaContent.indexOfChild(removed.view?.player) <=
+ activeMediaIndex
+ mediaContent.removeView(removed.view?.player)
+ removed.onDestroy()
+ updateMediaPaddings()
+ if (beforeActive) {
+ // also update the index here since the scroll below might not always lead
+ // to a scrolling changed
+ activeMediaIndex = Math.max(0, activeMediaIndex - 1)
+ mediaCarousel.scrollX = Math.max(mediaCarousel.scrollX -
+ playerWidthPlusPadding, 0)
+ }
+ updatePlayerVisibilities()
+ updatePageIndicator()
+ }
+ }
+
+ private fun recreatePlayers() {
+ // Note that this will scramble the order of players. Actively playing sessions will, at
+ // least, still be put in the front. If we want to maintain order, then more work is
+ // needed.
+ mediaData.forEach {
+ key, data ->
+ removePlayer(key)
+ addOrUpdatePlayer(key = key, oldKey = null, data = data)
+ }
}
private fun updateMediaPaddings() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index b93e07e65c73..d92434678357 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -202,14 +202,15 @@ public class PipTaskOrganizer extends TaskOrganizer implements
public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
@Nullable Divider divider,
- @NonNull DisplayController displayController) {
+ @NonNull DisplayController displayController,
+ @NonNull PipAnimationController pipAnimationController) {
mMainHandler = new Handler(Looper.getMainLooper());
mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
mPipBoundsHandler = boundsHandler;
mEnterExitAnimationDuration = context.getResources()
.getInteger(R.integer.config_pipResizeAnimationDuration);
mSurfaceTransactionHelper = surfaceTransactionHelper;
- mPipAnimationController = new PipAnimationController(context, surfaceTransactionHelper);
+ mPipAnimationController = pipAnimationController;
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
mSplitDivider = divider;
displayController.addDisplayWindowListener(this);
@@ -708,6 +709,12 @@ public class PipTaskOrganizer extends TaskOrganizer implements
Log.w(TAG, "Abort animation, invalid leash");
return;
}
+
+ if (startBounds.isEmpty() || destinationBounds.isEmpty()) {
+ Log.w(TAG, "Attempted to user resize PIP to or from empty bounds, aborting.");
+ return;
+ }
+
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, destinationBounds);
tx.apply();
@@ -738,9 +745,9 @@ public class PipTaskOrganizer extends TaskOrganizer implements
// on the task to ensure that the task "matches" the parent's bounds.
taskBounds = (direction == TRANSITION_DIRECTION_TO_FULLSCREEN)
? null : destinationBounds;
- // As for the final windowing mode, simply reset it to undefined and reset the activity
- // mode set prior to the animation running
- wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+ // Reset the final windowing mode.
+ wct.setWindowingMode(mToken, getOutPipWindowingMode());
+ // Simply reset the activity mode set prior to the animation running.
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
if (mSplitDivider != null && direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN) {
wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */);
@@ -752,9 +759,30 @@ public class PipTaskOrganizer extends TaskOrganizer implements
wct.setBounds(mToken, taskBounds);
wct.setBoundsChangeTransaction(mToken, tx);
+ applyFinishBoundsResize(wct, direction);
+ }
+
+ /**
+ * Applies the window container transaction to finish a bounds resize.
+ *
+ * Called by {@link #finishResize(SurfaceControl.Transaction, Rect, int, int)}} once it has
+ * finished preparing the transaction. It allows subclasses to modify the transaction before
+ * applying it.
+ */
+ public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct,
+ @PipAnimationController.TransitionDirection int direction) {
WindowOrganizer.applyTransaction(wct);
}
+ /**
+ * The windowing mode to restore to when resizing out of PIP direction. Defaults to undefined
+ * and can be overridden to restore to an alternate windowing mode.
+ */
+ public int getOutPipWindowingMode() {
+ // By default, simply reset the windowing mode to undefined.
+ return WINDOWING_MODE_UNDEFINED;
+ }
+
private void animateResizePip(Rect currentBounds, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction, int durationMs) {
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
index f1eef4353d32..8b3f4cb196bf 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.pip.phone;
+import android.content.Context;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
@@ -26,6 +27,10 @@ import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import com.android.systemui.R;
+import com.android.systemui.pip.PipSnapAlgorithm;
+import com.android.systemui.pip.PipTaskOrganizer;
+
import java.util.ArrayList;
import java.util.List;
@@ -43,16 +48,30 @@ public class PipAccessibilityInteractionConnection
private static final long ACCESSIBILITY_NODE_ID = 1;
private List<AccessibilityNodeInfo> mAccessibilityNodeInfoList;
+ private Context mContext;
private Handler mHandler;
private PipMotionHelper mMotionHelper;
+ private PipTaskOrganizer mTaskOrganizer;
+ private PipSnapAlgorithm mSnapAlgorithm;
+ private Runnable mUpdateMovementBoundCallback;
private AccessibilityCallbacks mCallbacks;
+ private final Rect mNormalBounds = new Rect();
+ private final Rect mExpandedBounds = new Rect();
+ private final Rect mNormalMovementBounds = new Rect();
+ private final Rect mExpandedMovementBounds = new Rect();
private Rect mTmpBounds = new Rect();
- public PipAccessibilityInteractionConnection(PipMotionHelper motionHelper,
- AccessibilityCallbacks callbacks, Handler handler) {
+ public PipAccessibilityInteractionConnection(Context context, PipMotionHelper motionHelper,
+ PipTaskOrganizer taskOrganizer, PipSnapAlgorithm snapAlgorithm,
+ AccessibilityCallbacks callbacks, Runnable updateMovementBoundCallback,
+ Handler handler) {
+ mContext = context;
mHandler = handler;
mMotionHelper = motionHelper;
+ mTaskOrganizer = taskOrganizer;
+ mSnapAlgorithm = snapAlgorithm;
+ mUpdateMovementBoundCallback = updateMovementBoundCallback;
mCallbacks = callbacks;
}
@@ -78,34 +97,46 @@ public class PipAccessibilityInteractionConnection
// We only support one view. A request for anything else is invalid
boolean result = false;
if (accessibilityNodeId == AccessibilityNodeInfo.ROOT_NODE_ID) {
- switch (action) {
- case AccessibilityNodeInfo.ACTION_CLICK:
- mHandler.post(() -> {
- mCallbacks.onAccessibilityShowMenu();
- });
- result = true;
- break;
- case AccessibilityNodeInfo.ACTION_DISMISS:
- mMotionHelper.dismissPip();
- result = true;
- break;
- case com.android.internal.R.id.accessibilityActionMoveWindow:
- int newX = arguments.getInt(
- AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_X);
- int newY = arguments.getInt(
- AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_Y);
- Rect pipBounds = new Rect();
- pipBounds.set(mMotionHelper.getBounds());
- mTmpBounds.offsetTo(newX, newY);
- mMotionHelper.movePip(mTmpBounds);
- result = true;
- break;
- case AccessibilityNodeInfo.ACTION_EXPAND:
- mMotionHelper.expandPipToFullscreen();
- result = true;
- break;
- default:
- // Leave result as false
+
+ // R constants are not final so this cannot be put in the switch-case.
+ if (action == R.id.action_pip_resize) {
+ if (mMotionHelper.getBounds().width() == mNormalBounds.width()
+ && mMotionHelper.getBounds().height() == mNormalBounds.height()) {
+ setToExpandedBounds();
+ } else {
+ setToNormalBounds();
+ }
+ result = true;
+ } else {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_CLICK:
+ mHandler.post(() -> {
+ mCallbacks.onAccessibilityShowMenu();
+ });
+ result = true;
+ break;
+ case AccessibilityNodeInfo.ACTION_DISMISS:
+ mMotionHelper.dismissPip();
+ result = true;
+ break;
+ case com.android.internal.R.id.accessibilityActionMoveWindow:
+ int newX = arguments.getInt(
+ AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_X);
+ int newY = arguments.getInt(
+ AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_Y);
+ Rect pipBounds = new Rect();
+ pipBounds.set(mMotionHelper.getBounds());
+ mTmpBounds.offsetTo(newX, newY);
+ mMotionHelper.movePip(mTmpBounds);
+ result = true;
+ break;
+ case AccessibilityNodeInfo.ACTION_EXPAND:
+ mMotionHelper.expandPipToFullscreen();
+ result = true;
+ break;
+ default:
+ // Leave result as false
+ }
}
}
try {
@@ -115,6 +146,27 @@ public class PipAccessibilityInteractionConnection
}
}
+ private void setToExpandedBounds() {
+ float savedSnapFraction = mSnapAlgorithm.getSnapFraction(
+ new Rect(mTaskOrganizer.getLastReportedBounds()), mNormalMovementBounds);
+ mSnapAlgorithm.applySnapFraction(mExpandedBounds, mExpandedMovementBounds,
+ savedSnapFraction);
+ mTaskOrganizer.scheduleFinishResizePip(mExpandedBounds, (Rect bounds) -> {
+ mMotionHelper.synchronizePinnedStackBounds();
+ mUpdateMovementBoundCallback.run();
+ });
+ }
+
+ private void setToNormalBounds() {
+ float savedSnapFraction = mSnapAlgorithm.getSnapFraction(
+ new Rect(mTaskOrganizer.getLastReportedBounds()), mExpandedMovementBounds);
+ mSnapAlgorithm.applySnapFraction(mNormalBounds, mNormalMovementBounds, savedSnapFraction);
+ mTaskOrganizer.scheduleFinishResizePip(mNormalBounds, (Rect bounds) -> {
+ mMotionHelper.synchronizePinnedStackBounds();
+ mUpdateMovementBoundCallback.run();
+ });
+ }
+
@Override
public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
String viewId, Region interactiveRegion, int interactionId,
@@ -175,7 +227,21 @@ public class PipAccessibilityInteractionConnection
// Do nothing.
}
- public static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo() {
+ /**
+ * Update the normal and expanded bounds so they can be used for Resize.
+ */
+ void onMovementBoundsChanged(Rect normalBounds, Rect expandedBounds, Rect normalMovementBounds,
+ Rect expandedMovementBounds) {
+ mNormalBounds.set(normalBounds);
+ mExpandedBounds.set(expandedBounds);
+ mNormalMovementBounds.set(normalMovementBounds);
+ mExpandedMovementBounds.set(expandedMovementBounds);
+ }
+
+ /**
+ * Update the Root node with PIP Accessibility action items.
+ */
+ public static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo(Context context) {
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
info.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
@@ -183,6 +249,8 @@ public class PipAccessibilityInteractionConnection
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_MOVE_WINDOW);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+ info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.action_pip_resize,
+ context.getString(R.string.accessibility_action_pip_resize)));
info.setImportantForAccessibility(true);
info.setClickable(true);
info.setVisibleToUser(true);
@@ -193,7 +261,7 @@ public class PipAccessibilityInteractionConnection
if (mAccessibilityNodeInfoList == null) {
mAccessibilityNodeInfoList = new ArrayList<>(1);
}
- AccessibilityNodeInfo info = obtainRootAccessibilityNodeInfo();
+ AccessibilityNodeInfo info = obtainRootAccessibilityNodeInfo(mContext);
mAccessibilityNodeInfoList.clear();
mAccessibilityNodeInfoList.add(info);
return mAccessibilityNodeInfoList;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index e38bfb441a0b..d195e1ca2510 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -81,12 +81,12 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
private InputConsumerController mInputConsumerController;
private PipMediaController mMediaController;
private PipTouchHandler mTouchHandler;
+ private PipTaskOrganizer mPipTaskOrganizer;
private PipAppOpsListener mAppOpsListener;
private IPinnedStackAnimationListener mPinnedStackAnimationRecentsListener;
private boolean mIsInFixedRotation;
protected PipMenuActivityController mMenuController;
- protected PipTaskOrganizer mPipTaskOrganizer;
/**
* Handler for display rotation changes.
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 6ab73fcce399..204354645e10 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -110,6 +110,8 @@ public class PipMenuActivity extends Activity {
private static final float DISABLED_ACTION_ALPHA = 0.54f;
+ private static final boolean ENABLE_RESIZE_HANDLE = false;
+
private int mMenuState;
private boolean mResize = true;
private boolean mAllowMenuTimeout = true;
@@ -388,7 +390,8 @@ public class PipMenuActivity extends Activity {
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 1f);
ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
- mResizeHandle.getAlpha(), menuState == MENU_STATE_CLOSE && showResizeHandle
+ mResizeHandle.getAlpha(),
+ ENABLE_RESIZE_HANDLE && menuState == MENU_STATE_CLOSE && showResizeHandle
? 1f : 0f);
if (menuState == MENU_STATE_FULL) {
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 856c19290af6..26805050e841 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Debug;
import android.util.Log;
@@ -38,6 +39,9 @@ import com.android.systemui.util.magnetictarget.MagnetizedObject;
import java.io.PrintWriter;
import java.util.function.Consumer;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+
/**
* A helper to animate and manipulate the PiP.
*/
@@ -74,9 +78,15 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
new SfVsyncFrameCallbackProvider();
/**
- * Bounds that are animated using the physics animator.
+ * Temporary bounds used when PIP is being dragged or animated. These bounds are applied to PIP
+ * using {@link PipTaskOrganizer#scheduleUserResizePip}, so that we can animate shrinking into
+ * and expanding out of the magnetic dismiss target.
+ *
+ * Once PIP is done being dragged or animated, we set {@link #mBounds} equal to these temporary
+ * bounds, and call {@link PipTaskOrganizer#scheduleFinishResizePip} to 'officially' move PIP to
+ * its new bounds.
*/
- private final Rect mAnimatedBounds = new Rect();
+ private final Rect mTemporaryBounds = new Rect();
/** The destination bounds to which PIP is animating. */
private final Rect mAnimatingToBounds = new Rect();
@@ -85,20 +95,20 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private FloatingContentCoordinator mFloatingContentCoordinator;
/** Callback that re-sizes PIP to the animated bounds. */
- private final Choreographer.FrameCallback mResizePipVsyncCallback =
- l -> resizePipUnchecked(mAnimatedBounds);
+ private final Choreographer.FrameCallback mResizePipVsyncCallback;
/**
- * PhysicsAnimator instance for animating {@link #mAnimatedBounds} using physics animations.
+ * PhysicsAnimator instance for animating {@link #mTemporaryBounds} using physics animations.
*/
- private PhysicsAnimator<Rect> mAnimatedBoundsPhysicsAnimator = PhysicsAnimator.getInstance(
- mAnimatedBounds);
+ private PhysicsAnimator<Rect> mTemporaryBoundsPhysicsAnimator = PhysicsAnimator.getInstance(
+ mTemporaryBounds);
+
+ private MagnetizedObject<Rect> mMagnetizedPip;
/**
- * Update listener that resizes the PIP to {@link #mAnimatedBounds}.
+ * Update listener that resizes the PIP to {@link #mTemporaryBounds}.
*/
- final PhysicsAnimator.UpdateListener<Rect> mResizePipUpdateListener =
- (target, values) -> mSfVsyncFrameProvider.postFrameCallback(mResizePipVsyncCallback);
+ private final PhysicsAnimator.UpdateListener<Rect> mResizePipUpdateListener;
/** FlingConfig instances provided to PhysicsAnimator for fling gestures. */
private PhysicsAnimator.FlingConfig mFlingConfigX;
@@ -124,6 +134,12 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private boolean mSpringingToTouch = false;
/**
+ * Whether PIP was released in the dismiss target, and will be animated out and dismissed
+ * shortly.
+ */
+ private boolean mDismissalPending = false;
+
+ /**
* Gets set in {@link #animateToExpandedState(Rect, Rect, Rect, Runnable)}, this callback is
* used to show menu activity when the expand animation is completed.
*/
@@ -155,6 +171,16 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mSnapAlgorithm = snapAlgorithm;
mFloatingContentCoordinator = floatingContentCoordinator;
mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
+
+ mResizePipVsyncCallback = l -> {
+ if (!mTemporaryBounds.isEmpty()) {
+ mPipTaskOrganizer.scheduleUserResizePip(
+ mBounds, mTemporaryBounds, null);
+ }
+ };
+
+ mResizePipUpdateListener = (target, values) ->
+ mSfVsyncFrameProvider.postFrameCallback(mResizePipVsyncCallback);
}
@NonNull
@@ -180,25 +206,15 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
void synchronizePinnedStackBounds() {
cancelAnimations();
mBounds.set(mPipTaskOrganizer.getLastReportedBounds());
+ mTemporaryBounds.setEmpty();
if (mPipTaskOrganizer.isInPip()) {
mFloatingContentCoordinator.onContentMoved(this);
}
}
- /**
- * Synchronizes the current bounds with either the pinned stack, or the ongoing animation. This
- * is done to prepare for a touch gesture.
- */
- void synchronizePinnedStackBoundsForTouchGesture() {
- if (mAnimatingToBounds.isEmpty()) {
- // If we're not animating anywhere, sync normally.
- synchronizePinnedStackBounds();
- } else {
- // If we're animating, set the current bounds to the animated bounds. That way, the
- // touch gesture will begin at the most recent animated location of the bounds.
- mBounds.set(mAnimatedBounds);
- }
+ boolean isAnimating() {
+ return mTemporaryBoundsPhysicsAnimator.isRunning();
}
/**
@@ -224,32 +240,59 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
// If we are moving PIP directly to the touch event locations, cancel any animations and
// move PIP to the given bounds.
cancelAnimations();
- resizePipUnchecked(toBounds);
- mBounds.set(toBounds);
+
+ if (!isDragging) {
+ resizePipUnchecked(toBounds);
+ mBounds.set(toBounds);
+ } else {
+ mTemporaryBounds.set(toBounds);
+ mPipTaskOrganizer.scheduleUserResizePip(mBounds, mTemporaryBounds, null);
+ }
} else {
// If PIP is 'catching up' after being stuck in the dismiss target, update the animation
// to spring towards the new touch location.
- mAnimatedBoundsPhysicsAnimator
+ mTemporaryBoundsPhysicsAnimator
+ .spring(FloatProperties.RECT_WIDTH, mBounds.width(), mSpringConfig)
+ .spring(FloatProperties.RECT_HEIGHT, mBounds.height(), mSpringConfig)
.spring(FloatProperties.RECT_X, toBounds.left, mSpringConfig)
- .spring(FloatProperties.RECT_Y, toBounds.top, mSpringConfig)
- .withEndActions(() -> mSpringingToTouch = false);
+ .spring(FloatProperties.RECT_Y, toBounds.top, mSpringConfig);
startBoundsAnimator(toBounds.left /* toX */, toBounds.top /* toY */,
false /* dismiss */);
}
}
- /** Set whether we're springing-to-touch to catch up after being stuck in the dismiss target. */
- void setSpringingToTouch(boolean springingToTouch) {
- if (springingToTouch) {
- mAnimatedBounds.set(mBounds);
- }
+ /** Animates the PIP into the dismiss target, scaling it down. */
+ void animateIntoDismissTarget(
+ MagnetizedObject.MagneticTarget target,
+ float velX, float velY,
+ boolean flung, Function0<Unit> after) {
+ final PointF targetCenter = target.getCenterOnScreen();
- mSpringingToTouch = springingToTouch;
+ final float desiredWidth = mBounds.width() / 2;
+ final float desiredHeight = mBounds.height() / 2;
+
+ final float destinationX = targetCenter.x - (desiredWidth / 2f);
+ final float destinationY = targetCenter.y - (desiredHeight / 2f);
+
+ // If we're already in the dismiss target area, then there won't be a move to set the
+ // temporary bounds, so just initialize it to the current bounds
+ if (mTemporaryBounds.isEmpty()) {
+ mTemporaryBounds.set(mBounds);
+ }
+ mTemporaryBoundsPhysicsAnimator
+ .spring(FloatProperties.RECT_X, destinationX, velX, mSpringConfig)
+ .spring(FloatProperties.RECT_Y, destinationY, velY, mSpringConfig)
+ .spring(FloatProperties.RECT_WIDTH, desiredWidth, mSpringConfig)
+ .spring(FloatProperties.RECT_HEIGHT, desiredHeight, mSpringConfig)
+ .withEndActions(after);
+
+ startBoundsAnimator(destinationX, destinationY, false);
}
- void prepareForAnimation() {
- mAnimatedBounds.set(mBounds);
+ /** Set whether we're springing-to-touch to catch up after being stuck in the dismiss target. */
+ void setSpringingToTouch(boolean springingToTouch) {
+ mSpringingToTouch = springingToTouch;
}
/**
@@ -309,13 +352,22 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
}
/**
+ * Returns the PIP bounds if we're not animating, or the current, temporary animating bounds
+ * otherwise.
+ */
+ Rect getPossiblyAnimatingBounds() {
+ return mTemporaryBounds.isEmpty() ? mBounds : mTemporaryBounds;
+ }
+
+ /**
* Flings the PiP to the closest snap target.
*/
void flingToSnapTarget(
float velocityX, float velocityY,
@Nullable Runnable updateAction, @Nullable Runnable endAction) {
- mAnimatedBounds.set(mBounds);
- mAnimatedBoundsPhysicsAnimator
+ mTemporaryBoundsPhysicsAnimator
+ .spring(FloatProperties.RECT_WIDTH, mBounds.width(), mSpringConfig)
+ .spring(FloatProperties.RECT_HEIGHT, mBounds.height(), mSpringConfig)
.flingThenSpring(
FloatProperties.RECT_X, velocityX, mFlingConfigX, mSpringConfig,
true /* flingMustReachMinOrMax */)
@@ -324,13 +376,14 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
.withEndActions(endAction);
if (updateAction != null) {
- mAnimatedBoundsPhysicsAnimator.addUpdateListener(
+ mTemporaryBoundsPhysicsAnimator.addUpdateListener(
(target, values) -> updateAction.run());
}
final float xEndValue = velocityX < 0 ? mMovementBounds.left : mMovementBounds.right;
final float estimatedFlingYEndValue =
- PhysicsAnimator.estimateFlingEndValue(mBounds.top, velocityY, mFlingConfigY);
+ PhysicsAnimator.estimateFlingEndValue(
+ mTemporaryBounds.top, velocityY, mFlingConfigY);
startBoundsAnimator(xEndValue /* toX */, estimatedFlingYEndValue /* toY */,
false /* dismiss */);
@@ -341,8 +394,12 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* configuration
*/
void animateToBounds(Rect bounds, PhysicsAnimator.SpringConfig springConfig) {
- mAnimatedBounds.set(mBounds);
- mAnimatedBoundsPhysicsAnimator
+ if (!mTemporaryBoundsPhysicsAnimator.isRunning()) {
+ // Animate from the current bounds if we're not already animating.
+ mTemporaryBounds.set(mBounds);
+ }
+
+ mTemporaryBoundsPhysicsAnimator
.spring(FloatProperties.RECT_X, bounds.left, springConfig)
.spring(FloatProperties.RECT_Y, bounds.top, springConfig);
startBoundsAnimator(bounds.left /* toX */, bounds.top /* toY */,
@@ -353,18 +410,19 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* Animates the dismissal of the PiP off the edge of the screen.
*/
void animateDismiss() {
- mAnimatedBounds.set(mBounds);
-
// Animate off the bottom of the screen, then dismiss PIP.
- mAnimatedBoundsPhysicsAnimator
+ mTemporaryBoundsPhysicsAnimator
.spring(FloatProperties.RECT_Y,
- mBounds.bottom + mBounds.height(),
+ mMovementBounds.bottom + mBounds.height() * 2,
0,
mSpringConfig)
.withEndActions(this::dismissPip);
- startBoundsAnimator(mBounds.left /* toX */, mBounds.bottom + mBounds.height() /* toY */,
+ startBoundsAnimator(
+ mBounds.left /* toX */, mBounds.bottom + mBounds.height() /* toY */,
true /* dismiss */);
+
+ mDismissalPending = false;
}
/**
@@ -415,7 +473,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* Cancels all existing animations.
*/
private void cancelAnimations() {
- mAnimatedBoundsPhysicsAnimator.cancel();
+ mTemporaryBoundsPhysicsAnimator.cancel();
mAnimatingToBounds.setEmpty();
mSpringingToTouch = false;
}
@@ -449,15 +507,36 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
(int) toY + mBounds.height());
setAnimatingToBounds(mAnimatingToBounds);
- mAnimatedBoundsPhysicsAnimator
- .withEndActions(() -> {
- if (!dismiss) {
- mPipTaskOrganizer.scheduleFinishResizePip(mAnimatedBounds);
- }
- mAnimatingToBounds.setEmpty();
- })
- .addUpdateListener(mResizePipUpdateListener)
- .start();
+ if (!mTemporaryBoundsPhysicsAnimator.isRunning()) {
+ mTemporaryBoundsPhysicsAnimator
+ .addUpdateListener(mResizePipUpdateListener)
+ .withEndActions(this::onBoundsAnimationEnd);
+ }
+
+ mTemporaryBoundsPhysicsAnimator.start();
+ }
+
+ /**
+ * Notify that PIP was released in the dismiss target and will be animated out and dismissed
+ * shortly.
+ */
+ void notifyDismissalPending() {
+ mDismissalPending = true;
+ }
+
+ private void onBoundsAnimationEnd() {
+ if (!mDismissalPending
+ && !mSpringingToTouch
+ && !mMagnetizedPip.getObjectStuckToTarget()) {
+ mBounds.set(mTemporaryBounds);
+ mPipTaskOrganizer.scheduleFinishResizePip(mBounds);
+
+ mTemporaryBounds.setEmpty();
+ }
+
+ mAnimatingToBounds.setEmpty();
+ mSpringingToTouch = false;
+ mDismissalPending = false;
}
/**
@@ -503,25 +582,29 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* magnetic dismiss target so it can calculate PIP's size and position.
*/
MagnetizedObject<Rect> getMagnetizedPip() {
- return new MagnetizedObject<Rect>(
- mContext, mAnimatedBounds, FloatProperties.RECT_X, FloatProperties.RECT_Y) {
- @Override
- public float getWidth(@NonNull Rect animatedPipBounds) {
- return animatedPipBounds.width();
- }
-
- @Override
- public float getHeight(@NonNull Rect animatedPipBounds) {
- return animatedPipBounds.height();
- }
+ if (mMagnetizedPip == null) {
+ mMagnetizedPip = new MagnetizedObject<Rect>(
+ mContext, mTemporaryBounds, FloatProperties.RECT_X, FloatProperties.RECT_Y) {
+ @Override
+ public float getWidth(@NonNull Rect animatedPipBounds) {
+ return animatedPipBounds.width();
+ }
+
+ @Override
+ public float getHeight(@NonNull Rect animatedPipBounds) {
+ return animatedPipBounds.height();
+ }
+
+ @Override
+ public void getLocationOnScreen(
+ @NonNull Rect animatedPipBounds, @NonNull int[] loc) {
+ loc[0] = animatedPipBounds.left;
+ loc[1] = animatedPipBounds.top;
+ }
+ };
+ }
- @Override
- public void getLocationOnScreen(
- @NonNull Rect animatedPipBounds, @NonNull int[] loc) {
- loc[0] = animatedPipBounds.left;
- loc[1] = animatedPipBounds.top;
- }
- };
+ return mMagnetizedPip;
}
public void dump(PrintWriter pw, String prefix) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 3cc9127068bf..7996316397e2 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -70,6 +70,8 @@ import com.android.systemui.util.magnetictarget.MagnetizedObject;
import java.io.PrintWriter;
+import kotlin.Unit;
+
/**
* Manages all the touch handling for PIP on the Phone, including moving, dismissing and expanding
* the PIP.
@@ -80,6 +82,9 @@ public class PipTouchHandler {
/** Duration of the dismiss scrim fading in/out. */
private static final int DISMISS_TRANSITION_DURATION_MS = 200;
+ /* The multiplier to apply scale the target size by when applying the magnetic field radius */
+ private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
+
// Allow dragging the PIP to a location to close it
private final boolean mEnableDismissDragToEdge;
// Allow PIP to resize to a slightly bigger state upon touch
@@ -122,7 +127,7 @@ public class PipTouchHandler {
/** Default configuration to use for springing the dismiss target in/out. */
private final PhysicsAnimator.SpringConfig mTargetSpringConfig =
new PhysicsAnimator.SpringConfig(
- SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_NO_BOUNCY);
+ SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
// The current movement bounds
private Rect mMovementBounds = new Rect();
@@ -248,8 +253,9 @@ public class PipTouchHandler {
mPipBoundsHandler = pipBoundsHandler;
mFloatingContentCoordinator = floatingContentCoordinator;
- mConnection = new PipAccessibilityInteractionConnection(mMotionHelper,
- this::onAccessibilityShowMenu, mHandler);
+ mConnection = new PipAccessibilityInteractionConnection(mContext, mMotionHelper,
+ pipTaskOrganizer, pipSnapAlgorithm, this::onAccessibilityShowMenu,
+ this::updateMovementBounds, mHandler);
mTargetView = new DismissCircleView(context);
mTargetViewContainer = new FrameLayout(context);
@@ -262,12 +268,14 @@ public class PipTouchHandler {
mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
updateMagneticTargetSize();
- mMagnetizedPip.setPhysicsAnimatorUpdateListener(mMotionHelper.mResizePipUpdateListener);
+ mMagnetizedPip.setAnimateStuckToTarget(
+ (target, velX, velY, flung, after) -> {
+ mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, after);
+ return Unit.INSTANCE;
+ });
mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
@Override
public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
- mMotionHelper.prepareForAnimation();
-
// Show the dismiss target, in case the initial touch event occurred within the
// magnetic field radius.
showDismissTargetMaybe();
@@ -286,12 +294,13 @@ public class PipTouchHandler {
@Override
public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+ mMotionHelper.notifyDismissalPending();
+
mHandler.post(() -> {
mMotionHelper.animateDismiss();
hideDismissTarget();
});
-
MetricsLoggerWrapper.logPictureInPictureDismissByDrag(mContext,
PipUtils.getTopPipActivity(mContext, mActivityManager));
}
@@ -319,11 +328,14 @@ public class PipTouchHandler {
final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
final FrameLayout.LayoutParams newParams =
new FrameLayout.LayoutParams(targetSize, targetSize);
- newParams.gravity = Gravity.CENTER;
+ newParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+ newParams.bottomMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.floating_dismiss_bottom_margin);
mTargetView.setLayoutParams(newParams);
- // Set the magnetic field radius equal to twice the size of the target.
- mMagneticTarget.setMagneticFieldRadiusPx(targetSize * 2);
+ // Set the magnetic field radius equal to the target size from the center of the target
+ mMagneticTarget.setMagneticFieldRadiusPx(
+ (int) (targetSize * MAGNETIC_FIELD_RADIUS_MULTIPLIER));
}
private boolean shouldShowResizeHandle() {
@@ -462,9 +474,9 @@ public class PipTouchHandler {
// touching the screen
} else {
final boolean isExpanded = mMenuState == MENU_STATE_FULL && willResizeMenu();
- final Rect toMovementBounds = isExpanded
- ? new Rect(expandedMovementBounds)
- : new Rect(normalMovementBounds);
+ final Rect toMovementBounds = new Rect();
+ mSnapAlgorithm.getMovementBounds(curBounds, insetBounds,
+ toMovementBounds, mIsImeShowing ? mImeHeight : 0);
final int prevBottom = mMovementBounds.bottom - mMovementBoundsExtraOffsets;
final int toBottom = toMovementBounds.bottom < toMovementBounds.top
? toMovementBounds.bottom
@@ -492,6 +504,8 @@ public class PipTouchHandler {
mInsetBounds.set(insetBounds);
updateMovementBounds();
mMovementBoundsExtraOffsets = extraOffset;
+ mConnection.onMovementBoundsChanged(mNormalBounds, mExpandedBounds, mNormalMovementBounds,
+ mExpandedMovementBounds);
// If we have a deferred resize, apply it now
if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {
@@ -617,11 +631,16 @@ public class PipTouchHandler {
}
MotionEvent ev = (MotionEvent) inputEvent;
-
- if (mPipResizeGestureHandler.isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY())) {
+ if (!mTouchState.isDragging()
+ && !mMagnetizedPip.getObjectStuckToTarget()
+ && !mMotionHelper.isAnimating()
+ && mPipResizeGestureHandler.isWithinTouchRegion(
+ (int) ev.getRawX(), (int) ev.getRawY())) {
return true;
}
- if (mMagnetizedPip.maybeConsumeMotionEvent(ev)) {
+
+ if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
+ && mMagnetizedPip.maybeConsumeMotionEvent(ev)) {
// If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
// to the touch state. Touch state needs a DOWN event in order to later process MOVE
// events it'll receive if the object is dragged out of the magnetic field.
@@ -643,7 +662,6 @@ public class PipTouchHandler {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
- mMotionHelper.synchronizePinnedStackBoundsForTouchGesture();
mGesture.onDown(mTouchState);
break;
}
@@ -688,11 +706,11 @@ public class PipTouchHandler {
break;
}
case MotionEvent.ACTION_HOVER_EXIT: {
- mHideMenuAfterShown = true;
// If Touch Exploration is enabled, some a11y services (e.g. Talkback) is probably
// on and changing MotionEvents into HoverEvents.
// Let's not enable menu show/hide for a11y services.
if (!mAccessibilityManager.isTouchExplorationEnabled()) {
+ mHideMenuAfterShown = true;
mMenuController.hideMenu();
}
if (!shouldDeliverToMenu && mSendingHoverAccessibilityEvents) {
@@ -872,7 +890,7 @@ public class PipTouchHandler {
return;
}
- Rect bounds = mMotionHelper.getBounds();
+ Rect bounds = mMotionHelper.getPossiblyAnimatingBounds();
mDelta.set(0f, 0f);
mStartPosition.set(bounds.left, bounds.top);
mMovementWithinDismiss = touchState.getDownTouchPosition().y >= mMovementBounds.bottom;
@@ -914,7 +932,7 @@ public class PipTouchHandler {
mDelta.x += left - lastX;
mDelta.y += top - lastY;
- mTmpBounds.set(mMotionHelper.getBounds());
+ mTmpBounds.set(mMotionHelper.getPossiblyAnimatingBounds());
mTmpBounds.offsetTo((int) left, (int) top);
mMotionHelper.movePip(mTmpBounds, true /* isDragging */);
@@ -939,7 +957,6 @@ public class PipTouchHandler {
}
final PointF vel = touchState.getVelocity();
- final float velocity = PointF.length(vel.x, vel.y);
if (touchState.isDragging()) {
if (mMenuState != MENU_STATE_NONE) {
@@ -1030,6 +1047,7 @@ public class PipTouchHandler {
pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
pw.println(innerPrefix + "mEnableDragToEdgeDismiss=" + mEnableDismissDragToEdge);
+ pw.println(innerPrefix + "mMovementBoundsExtraOffsets=" + mMovementBoundsExtraOffsets);
mTouchState.dump(pw, innerPrefix);
mMotionHelper.dump(pw, innerPrefix);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index 4be0c157de8e..132c04d381dd 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -31,7 +31,7 @@ import java.io.PrintWriter;
* This keeps track of the touch state throughout the current touch gesture.
*/
public class PipTouchState {
- private static final String TAG = "PipTouchHandler";
+ private static final String TAG = "PipTouchState";
private static final boolean DEBUG = false;
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
index 2365e67fec2f..0a84f5ee1bb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
@@ -23,6 +23,7 @@ import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
+import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -30,6 +31,7 @@ import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Prefs;
import com.android.systemui.Prefs.Key;
+import com.android.systemui.util.UserAwareController;
import java.util.Arrays;
import java.util.Collection;
@@ -37,7 +39,7 @@ import java.util.Collections;
import javax.inject.Inject;
-public class AutoAddTracker {
+public class AutoAddTracker implements UserAwareController {
private static final String[][] CONVERT_PREFS = {
{Key.QS_HOTSPOT_ADDED, HOTSPOT},
@@ -49,20 +51,39 @@ public class AutoAddTracker {
private final ArraySet<String> mAutoAdded;
private final Context mContext;
+ private int mUserId;
- @Inject
- public AutoAddTracker(Context context) {
+ public AutoAddTracker(Context context, int userId) {
mContext = context;
+ mUserId = userId;
mAutoAdded = new ArraySet<>(getAdded());
// TODO: remove migration code and shared preferences keys after P release
- for (String[] convertPref : CONVERT_PREFS) {
- if (Prefs.getBoolean(context, convertPref[0], false)) {
- setTileAdded(convertPref[1]);
- Prefs.remove(context, convertPref[0]);
+ if (mUserId == UserHandle.USER_SYSTEM) {
+ for (String[] convertPref : CONVERT_PREFS) {
+ if (Prefs.getBoolean(context, convertPref[0], false)) {
+ setTileAdded(convertPref[1]);
+ Prefs.remove(context, convertPref[0]);
+ }
}
}
mContext.getContentResolver().registerContentObserver(
- Secure.getUriFor(Secure.QS_AUTO_ADDED_TILES), false, mObserver);
+ Secure.getUriFor(Secure.QS_AUTO_ADDED_TILES), false, mObserver,
+ UserHandle.USER_ALL);
+ }
+
+ @Override
+ public void changeUser(UserHandle newUser) {
+ if (newUser.getIdentifier() == mUserId) {
+ return;
+ }
+ mUserId = newUser.getIdentifier();
+ mAutoAdded.clear();
+ mAutoAdded.addAll(getAdded());
+ }
+
+ @Override
+ public int getCurrentUserId() {
+ return mUserId;
}
public boolean isAdded(String tile) {
@@ -86,12 +107,13 @@ public class AutoAddTracker {
}
private void saveTiles() {
- Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES,
- TextUtils.join(",", mAutoAdded));
+ Secure.putStringForUser(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES,
+ TextUtils.join(",", mAutoAdded), mUserId);
}
private Collection<String> getAdded() {
- String current = Secure.getString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES);
+ String current = Secure.getStringForUser(mContext.getContentResolver(),
+ Secure.QS_AUTO_ADDED_TILES, mUserId);
if (current == null) {
return Collections.emptyList();
}
@@ -102,7 +124,27 @@ public class AutoAddTracker {
protected final ContentObserver mObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
+ mAutoAdded.clear();
mAutoAdded.addAll(getAdded());
}
};
+
+ public static class Builder {
+ private final Context mContext;
+ private int mUserId;
+
+ @Inject
+ public Builder(Context context) {
+ mContext = context;
+ }
+
+ public Builder setUserId(int userId) {
+ mUserId = userId;
+ return this;
+ }
+
+ public AutoAddTracker build() {
+ return new AutoAddTracker(mContext, mUserId);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 7bcaa7263cc4..51eca67e02f9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -148,14 +148,19 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
final String vpnName = mSecurityController.getPrimaryVpnName();
final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
final CharSequence organizationName = mSecurityController.getDeviceOwnerOrganizationName();
- final CharSequence workProfileName = mSecurityController.getWorkProfileOrganizationName();
+ final CharSequence workProfileOrganizationName =
+ mSecurityController.getWorkProfileOrganizationName();
+ final boolean isProfileOwnerOfOrganizationOwnedDevice =
+ mSecurityController.isProfileOwnerOfOrganizationOwnedDevice();
// Update visibility of footer
- mIsVisible = (isDeviceManaged && !isDemoDevice) || hasCACerts || hasCACertsInWorkProfile ||
- vpnName != null || vpnNameWorkProfile != null;
+ mIsVisible = (isDeviceManaged && !isDemoDevice) || hasCACerts || hasCACertsInWorkProfile
+ || vpnName != null || vpnNameWorkProfile != null
+ || isProfileOwnerOfOrganizationOwnedDevice;
// Update the string
mFooterTextContent = getFooterText(isDeviceManaged, hasWorkProfile,
hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
- vpnNameWorkProfile, organizationName, workProfileName);
+ vpnNameWorkProfile, organizationName, workProfileOrganizationName,
+ isProfileOwnerOfOrganizationOwnedDevice);
// Update the icon
int footerIconId = R.drawable.ic_info_outline;
if (vpnName != null || vpnNameWorkProfile != null) {
@@ -175,7 +180,8 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
- CharSequence workProfileName) {
+ CharSequence workProfileOrganizationName,
+ boolean isProfileOwnerOfOrganizationOwnedDevice) {
if (isDeviceManaged || DEBUG_FORCE_VISIBLE) {
if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
if (organizationName == null) {
@@ -211,13 +217,13 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
organizationName);
} // end if(isDeviceManaged)
if (hasCACertsInWorkProfile) {
- if (workProfileName == null) {
+ if (workProfileOrganizationName == null) {
return mContext.getString(
R.string.quick_settings_disclosure_managed_profile_monitoring);
}
return mContext.getString(
R.string.quick_settings_disclosure_named_managed_profile_monitoring,
- workProfileName);
+ workProfileOrganizationName);
}
if (hasCACerts) {
return mContext.getString(R.string.quick_settings_disclosure_monitoring);
@@ -238,6 +244,13 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
vpnName);
}
+ if (isProfileOwnerOfOrganizationOwnedDevice) {
+ if (workProfileOrganizationName == null) {
+ return mContext.getString(R.string.quick_settings_disclosure_management);
+ }
+ return mContext.getString(R.string.quick_settings_disclosure_named_management,
+ workProfileOrganizationName);
+ }
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 65d3572d04a3..1f3967c03a41 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -255,6 +255,9 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
int currentUser = ActivityManager.getCurrentUser();
if (currentUser != mCurrentUser) {
mUserContext = mContext.createContextAsUser(UserHandle.of(currentUser), 0);
+ if (mAutoTiles != null) {
+ mAutoTiles.changeUser(UserHandle.of(currentUser));
+ }
}
if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser) return;
mTiles.entrySet().stream().filter(tile -> !tileSpecs.contains(tile.getKey())).forEach(
@@ -474,7 +477,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
tiles.addAll(Arrays.asList(defaultTileList.split(",")));
if (Build.IS_DEBUGGABLE
- && GarbageMonitor.MemoryTile.ADD_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
+ && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
}
return tiles;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 8c1e1dd0cac7..33f0f4d8618b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -18,10 +18,8 @@ package com.android.systemui.screenshot;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_SCROLLING_ENABLED;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
import android.animation.Animator;
@@ -51,7 +49,6 @@ import android.graphics.Region;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.LayerDrawable;
import android.media.MediaActionSound;
@@ -62,7 +59,6 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -626,7 +622,7 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
/**
* Clears current screenshot
*/
- private void dismissScreenshot(String reason, boolean immediate) {
+ void dismissScreenshot(String reason, boolean immediate) {
Log.v(TAG, "clearing screenshot: " + reason);
mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
mScreenshotLayout.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
@@ -955,22 +951,6 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
});
mScreenshotPreview.setContentDescription(imageData.editAction.title);
- if (DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, SCREENSHOT_SCROLLING_ENABLED, false)) {
- ScreenshotActionChip scrollChip = (ScreenshotActionChip) inflater.inflate(
- R.layout.global_screenshot_action_chip, mActionsView, false);
- Toast scrollNotImplemented = Toast.makeText(
- mContext, "Not implemented", Toast.LENGTH_SHORT);
- scrollChip.setText("Extend"); // TODO: add resource and translate
- scrollChip.setIcon(
- Icon.createWithResource(mContext, R.drawable.ic_arrow_downward), true);
- scrollChip.setOnClickListener(v -> {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SCROLL_TAPPED);
- scrollNotImplemented.show();
- });
- mActionsView.addView(scrollChip);
- chips.add(scrollChip);
- }
-
// remove the margin from the last chip so that it's correctly aligned with the end
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
mActionsView.getChildAt(mActionsView.getChildCount() - 1).getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index c05c8236def0..9f8a9bb4a432 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -16,12 +16,17 @@
package com.android.systemui.screenshot;
+import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
+
import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_PROCESS_COMPLETE;
import static com.android.internal.util.ScreenshotHelper.SCREENSHOT_MSG_URI;
import android.app.Service;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -51,6 +56,16 @@ public class TakeScreenshotService extends Service {
private final UserManager mUserManager;
private final UiEventLogger mUiEventLogger;
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction()) && mScreenshot != null) {
+ mScreenshot.dismissScreenshot("close system dialogs", true);
+ }
+ }
+ };
+
private Handler mHandler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -119,12 +134,18 @@ public class TakeScreenshotService extends Service {
@Override
public IBinder onBind(Intent intent) {
+ // register broadcast receiver
+ IntentFilter filter = new IntentFilter(ACTION_CLOSE_SYSTEM_DIALOGS);
+ registerReceiver(mBroadcastReceiver, filter);
+
return new Messenger(mHandler).getBinder();
+
}
@Override
public boolean onUnbind(Intent intent) {
if (mScreenshot != null) mScreenshot.stopScreenshot();
+ unregisterReceiver(mBroadcastReceiver);
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 21810c0e7cf5..03a0d930a3d9 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -127,7 +127,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
snap.calculateNonDismissingSnapTarget(position);
sdl.resizeSplits(target.position, t);
- if (isSplitActive()) {
+ if (isSplitActive() && mHomeStackResizable) {
WindowManagerProxy.applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
}
if (mWindowManagerProxy.queueSyncTransactionIfWaiting(t)) {
@@ -428,7 +428,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
}
private void updateTouchable() {
- mWindowManager.setTouchable((mHomeStackResizable || !mMinimized) && !mAdjustedForIme);
+ mWindowManager.setTouchable(!mAdjustedForIme);
}
/**
@@ -523,7 +523,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
}
void ensureMinimizedSplit() {
- setHomeMinimized(true /* minimized */, mSplits.mSecondary.isResizable());
+ setHomeMinimized(true /* minimized */, mHomeStackResizable);
if (!isDividerVisible()) {
// Wasn't in split-mode yet, so enter now.
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
index aea87f2d1971..d782a3cadc19 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
@@ -126,16 +126,16 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
@Override
public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
boolean imeShouldShow, SurfaceControl.Transaction t) {
+ mHiddenTop = hiddenTop;
+ mShownTop = shownTop;
+ mTargetShown = imeShouldShow;
if (!isDividerVisible()) {
return;
}
final boolean splitIsVisible = !getView().isHidden();
mSecondaryHasFocus = getSecondaryHasFocus(displayId);
final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
- && !getLayout().mDisplayLayout.isLandscape();
- mHiddenTop = hiddenTop;
- mShownTop = shownTop;
- mTargetShown = imeShouldShow;
+ && !getLayout().mDisplayLayout.isLandscape() && !mSplits.mDivider.isMinimized();
if (mLastAdjustTop < 0) {
mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
} else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 2271f6de194f..42d8c959371f 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -320,8 +320,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
super.onAttachedToWindow();
// Save the current target if not minimized once attached to window
- if (mHomeStackResizable && mDockSide != WindowManager.DOCKED_INVALID
- && !mIsInMinimizeInteraction) {
+ if (mDockSide != WindowManager.DOCKED_INVALID && !mIsInMinimizeInteraction) {
saveSnapTargetBeforeMinimized(mSnapTargetBeforeMinimized);
}
mFirstLayout = true;
@@ -470,8 +469,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
public DividerSnapAlgorithm getSnapAlgorithm() {
- return mDockedStackMinimized
- && mHomeStackResizable ? mSplitLayout.getMinimizedSnapAlgorithm()
+ return mDockedStackMinimized ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
: mSplitLayout.getSnapAlgorithm();
}
@@ -629,7 +627,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
// Record last snap target the divider moved to
- if (mHomeStackResizable && !mIsInMinimizeInteraction) {
+ if (!mIsInMinimizeInteraction) {
// The last snapTarget position can be negative when the last divider position was
// offscreen. In that case, save the middle (default) SnapTarget so calculating next
// position isn't negative.
@@ -774,7 +772,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
mSplitLayout.resizeSplits(midPos);
Transaction t = mTiles.getTransaction();
if (mDockedStackMinimized) {
- int position = mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget().position;
+ int position = mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
+ .getMiddleTarget().position;
calculateBoundsForPosition(position, mDockSide, mDockedRect);
calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
mOtherRect);
@@ -811,23 +810,9 @@ public class DividerView extends FrameLayout implements OnTouchListener,
updateDockSide();
if (!minimized) {
resetBackground();
- } else if (!isHomeStackResizable) {
- if (mDockSide == WindowManager.DOCKED_TOP) {
- mBackground.setPivotY(0);
- mBackground.setScaleY(MINIMIZE_DOCK_SCALE);
- } else if (mDockSide == WindowManager.DOCKED_LEFT
- || mDockSide == WindowManager.DOCKED_RIGHT) {
- mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
- ? 0
- : mBackground.getWidth());
- mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
- }
}
mMinimizedShadow.setAlpha(minimized ? 1f : 0f);
- if (!isHomeStackResizable) {
- mHandle.setAlpha(minimized ? 0f : 1f);
- mDockedStackMinimized = minimized;
- } else if (mDockedStackMinimized != minimized) {
+ if (mDockedStackMinimized != minimized) {
mDockedStackMinimized = minimized;
if (mSplitLayout.mDisplayLayout.rotation() != mDefaultDisplay.getRotation()) {
// Splitscreen to minimize is about to starts after rotating landscape to seascape,
@@ -840,8 +825,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
// Relayout to recalculate the divider shadow when minimizing
requestLayout();
mIsInMinimizeInteraction = true;
- resizeStackSurfaces(
- mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget(), t);
+ resizeStackSurfaces(mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
+ .getMiddleTarget(), t);
} else {
resizeStackSurfaces(mSnapTargetBeforeMinimized, t);
mIsInMinimizeInteraction = false;
@@ -860,11 +845,11 @@ public class DividerView extends FrameLayout implements OnTouchListener,
t.show(sc).apply();
mTiles.releaseTransaction(t);
});
- if (isHomeStackResizable) {
- SnapTarget miniMid = mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget();
- if (mDockedStackMinimized) {
- mDividerPositionY = mDividerPositionX = miniMid.position;
- }
+
+ SnapTarget miniMid =
+ mSplitLayout.getMinimizedSnapAlgorithm(isHomeStackResizable).getMiddleTarget();
+ if (mDockedStackMinimized) {
+ mDividerPositionY = mDividerPositionX = miniMid.position;
}
}
@@ -903,38 +888,15 @@ public class DividerView extends FrameLayout implements OnTouchListener,
if (DEBUG) Slog.d(TAG, "setMinDock: " + mDockedStackMinimized + "->" + minimized);
mHomeStackResizable = isHomeStackResizable;
updateDockSide();
- if (!isHomeStackResizable) {
- mMinimizedShadow.animate()
- .alpha(minimized ? 1f : 0f)
- .setInterpolator(Interpolators.ALPHA_IN)
- .setDuration(animDuration)
- .start();
- mHandle.animate()
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setDuration(animDuration)
- .alpha(minimized ? 0f : 1f)
- .start();
- if (mDockSide == WindowManager.DOCKED_TOP) {
- mBackground.setPivotY(0);
- mBackground.animate()
- .scaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f);
- } else if (mDockSide == WindowManager.DOCKED_LEFT
- || mDockSide == WindowManager.DOCKED_RIGHT) {
- mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
- ? 0
- : mBackground.getWidth());
- mBackground.animate()
- .scaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f);
- }
- mDockedStackMinimized = minimized;
- } else if (mDockedStackMinimized != minimized) {
+ if (mDockedStackMinimized != minimized) {
mIsInMinimizeInteraction = true;
mDockedStackMinimized = minimized;
stopDragging(minimized
? mSnapTargetBeforeMinimized.position
: getCurrentPosition(),
minimized
- ? mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget()
+ ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
+ .getMiddleTarget()
: mSnapTargetBeforeMinimized,
animDuration, Interpolators.FAST_OUT_SLOW_IN, 0);
setAdjustedForIme(false, animDuration);
@@ -1127,7 +1089,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
final boolean ownTransaction = transaction == null;
final Transaction t = ownTransaction ? mTiles.getTransaction() : transaction;
mLastResizeRect.set(mDockedRect);
- if (mHomeStackResizable && mIsInMinimizeInteraction) {
+ if (mIsInMinimizeInteraction) {
calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide,
mDockedTaskRect);
calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
@@ -1138,8 +1100,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
mDockedTaskRect.offset(Math.max(position, -mDividerSize)
- mDockedTaskRect.left + mDividerSize, 0);
}
- resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect,
- mOtherTaskRect);
+ resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
if (ownTransaction) {
t.apply();
mTiles.releaseTransaction(t);
@@ -1420,7 +1381,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
void onUndockingTask() {
int dockSide = mSplitLayout.getPrimarySplitSide();
- if (inSplitMode() && (mHomeStackResizable || !mDockedStackMinimized)) {
+ if (inSplitMode()) {
startDragging(false /* animate */, false /* touching */);
SnapTarget target = dockSideTopLeft(dockSide)
? mSplitLayout.getSnapAlgorithm().getDismissEndTarget()
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
index 92f6b4a2d8c4..69095f7538c5 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
@@ -16,8 +16,6 @@
package com.android.systemui.stackdivider;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.DOCKED_BOTTOM;
@@ -113,11 +111,6 @@ public class SplitDisplayLayout {
}
}
- boolean isMinimized() {
- return mTiles.mSecondary.topActivityType == ACTIVITY_TYPE_HOME
- || mTiles.mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS;
- }
-
DividerSnapAlgorithm getSnapAlgorithm() {
if (mSnapAlgorithm == null) {
updateResources();
@@ -129,14 +122,14 @@ public class SplitDisplayLayout {
return mSnapAlgorithm;
}
- DividerSnapAlgorithm getMinimizedSnapAlgorithm() {
+ DividerSnapAlgorithm getMinimizedSnapAlgorithm(boolean homeStackResizable) {
if (mMinimizedSnapAlgorithm == null) {
updateResources();
boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide(),
- true /* isMinimized */);
+ true /* isMinimized */, homeStackResizable);
}
return mMinimizedSnapAlgorithm;
}
@@ -168,8 +161,9 @@ public class SplitDisplayLayout {
mDisplayLayout.height(), mDividerSize);
}
- Rect calcMinimizedHomeStackBounds() {
- DividerSnapAlgorithm.SnapTarget miniMid = getMinimizedSnapAlgorithm().getMiddleTarget();
+ Rect calcResizableMinimizedHomeStackBounds() {
+ DividerSnapAlgorithm.SnapTarget miniMid =
+ getMinimizedSnapAlgorithm(true /* resizable */).getMiddleTarget();
Rect homeBounds = new Rect();
DockedDividerUtils.calculateBoundsForPosition(miniMid.position,
DockedDividerUtils.invertDockSide(getPrimarySplitSide()), homeBounds,
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index db324822994b..6751e8d6223d 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -165,8 +165,9 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
Log.e(TAG, "Got handleTaskInfoChanged when not initialized: " + info);
return;
}
- final boolean secondaryWasHomeOrRecents = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
- || mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS;
+ final boolean secondaryImpliedMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+ || (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
+ && mDivider.isHomeStackResizable());
final boolean primaryWasEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryWasEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
if (info.token.asBinder() == mPrimary.token.asBinder()) {
@@ -176,13 +177,14 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
}
final boolean primaryIsEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryIsEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
- final boolean secondaryIsHomeOrRecents = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
- || mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS;
+ final boolean secondaryImpliesMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+ || (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
+ && mDivider.isHomeStackResizable());
if (DEBUG) {
Log.d(TAG, "onTaskInfoChanged " + mPrimary + " " + mSecondary);
}
if (primaryIsEmpty == primaryWasEmpty && secondaryWasEmpty == secondaryIsEmpty
- && secondaryWasHomeOrRecents == secondaryIsHomeOrRecents) {
+ && secondaryImpliedMinimize == secondaryImpliesMinimize) {
// No relevant changes
return;
}
@@ -211,7 +213,7 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
}
mDivider.startEnterSplit();
}
- } else if (secondaryIsHomeOrRecents) {
+ } else if (secondaryImpliesMinimize) {
// Both splits are populated but the secondary split has a home/recents stack on top,
// so enter minimized mode.
mDivider.ensureMinimizedSplit();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 853a22505542..410e3dd39a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -19,6 +19,9 @@ package com.android.systemui.stackdivider;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import android.annotation.NonNull;
@@ -115,7 +118,7 @@ public class WindowManagerProxy {
WindowOrganizer.applyTransaction(t);
}
- private static boolean getHomeAndRecentsTasks(List<WindowContainerToken> out,
+ private static boolean getHomeAndRecentsTasks(List<ActivityManager.RunningTaskInfo> out,
WindowContainerToken parent) {
boolean resizable = false;
List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
@@ -123,9 +126,9 @@ public class WindowManagerProxy {
: TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
for (int i = 0, n = rootTasks.size(); i < n; ++i) {
final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
- out.add(ti.token);
+ out.add(ti);
if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
- resizable = ti.isResizable();
+ resizable = ti.isResizeable;
}
}
return resizable;
@@ -140,16 +143,37 @@ public class WindowManagerProxy {
@NonNull WindowContainerTransaction wct) {
// Resize the home/recents stacks to the larger minimized-state size
final Rect homeBounds;
- final ArrayList<WindowContainerToken> homeStacks = new ArrayList<>();
+ final ArrayList<ActivityManager.RunningTaskInfo> homeStacks = new ArrayList<>();
boolean isHomeResizable = getHomeAndRecentsTasks(homeStacks, parent);
if (isHomeResizable) {
- homeBounds = layout.calcMinimizedHomeStackBounds();
+ homeBounds = layout.calcResizableMinimizedHomeStackBounds();
} else {
- homeBounds = new Rect(0, 0, layout.mDisplayLayout.width(),
- layout.mDisplayLayout.height());
+ // home is not resizable, so lock it to its inherent orientation size.
+ homeBounds = new Rect(0, 0, 0, 0);
+ for (int i = homeStacks.size() - 1; i >= 0; --i) {
+ if (homeStacks.get(i).topActivityType == ACTIVITY_TYPE_HOME) {
+ final int orient = homeStacks.get(i).configuration.orientation;
+ final boolean displayLandscape = layout.mDisplayLayout.isLandscape();
+ final boolean isLandscape = orient == ORIENTATION_LANDSCAPE
+ || (orient == ORIENTATION_UNDEFINED && displayLandscape);
+ homeBounds.right = isLandscape == displayLandscape
+ ? layout.mDisplayLayout.width() : layout.mDisplayLayout.height();
+ homeBounds.bottom = isLandscape == displayLandscape
+ ? layout.mDisplayLayout.height() : layout.mDisplayLayout.width();
+ break;
+ }
+ }
}
for (int i = homeStacks.size() - 1; i >= 0; --i) {
- wct.setBounds(homeStacks.get(i), homeBounds);
+ // For non-resizable homes, the minimized size is actually the fullscreen-size. As a
+ // result, we don't minimize for recents since it only shows half-size screenshots.
+ if (!isHomeResizable) {
+ if (homeStacks.get(i).topActivityType == ACTIVITY_TYPE_RECENTS) {
+ continue;
+ }
+ wct.setWindowingMode(homeStacks.get(i).token, WINDOWING_MODE_FULLSCREEN);
+ }
+ wct.setBounds(homeStacks.get(i).token, homeBounds);
}
layout.mTiles.mHomeBounds.set(homeBounds);
return isHomeResizable;
@@ -175,11 +199,13 @@ public class WindowManagerProxy {
return false;
}
ActivityManager.RunningTaskInfo topHomeTask = null;
- boolean homeIsTop = false;
for (int i = rootTasks.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i);
- // Only move resizeable task to split secondary. WM will just ignore this anyways...
- if (!rootTask.isResizable()) continue;
+ // Only move resizeable task to split secondary. However, we have an exception
+ // for non-resizable home because we will minimize to show it.
+ if (!rootTask.isResizeable && rootTask.topActivityType != ACTIVITY_TYPE_HOME) {
+ continue;
+ }
// Only move fullscreen tasks to split secondary.
if (rootTask.configuration.windowConfiguration.getWindowingMode()
!= WINDOWING_MODE_FULLSCREEN) {
@@ -193,7 +219,7 @@ public class WindowManagerProxy {
// Move the secondary split-forward.
wct.reorder(tiles.mSecondary.token, true /* onTop */);
boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
- if (isHomeResizable && topHomeTask != null) {
+ if (topHomeTask != null) {
// Translate/update-crop of secondary out-of-band with sync transaction -- Until BALST
// is enabled, this temporarily syncs the home surface position with offset until
// sync transaction finishes.
@@ -253,6 +279,7 @@ public class WindowManagerProxy {
wct.reparent(ti.token, null /* parent */, true /* onTop */);
if (isHomeOrRecentTask(ti)) {
wct.setBounds(ti.token, null);
+ wct.setWindowingMode(ti.token, WINDOWING_MODE_UNDEFINED);
if (i == 0) {
homeOnTop = true;
}
@@ -293,8 +320,9 @@ public class WindowManagerProxy {
final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
if (isHomeOrRecentTask(ti)) {
wct.reparent(ti.token, null /* parent */, true /* onTop */);
- // reset bounds too
+ // reset bounds and mode too
wct.setBounds(ti.token, null);
+ wct.setWindowingMode(ti.token, WINDOWING_MODE_UNDEFINED);
}
}
for (int i = primaryChildren.size() - 1; i >= 0; --i) {
@@ -304,6 +332,7 @@ public class WindowManagerProxy {
}
for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
wct.setBounds(freeHomeAndRecents.get(i).token, null);
+ wct.setWindowingMode(freeHomeAndRecents.get(i).token, WINDOWING_MODE_UNDEFINED);
}
// Reset focusable to true
wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 6d2cc6b08bc4..7b2585324b9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -27,7 +27,6 @@ import android.os.SystemClock
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.ViewConfiguration
-
import com.android.systemui.Gefingerpoken
import com.android.systemui.Interpolators
import com.android.systemui.R
@@ -41,7 +40,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.ShadeController
-
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.max
@@ -162,10 +160,12 @@ constructor(
MotionEvent.ACTION_UP -> {
recycleVelocityTracker()
+ isExpanding = false
}
MotionEvent.ACTION_CANCEL -> {
recycleVelocityTracker()
+ isExpanding = false
}
}
return false
@@ -181,7 +181,8 @@ constructor(
return false
}
- if (!isExpanding || event.actionMasked == MotionEvent.ACTION_DOWN) {
+ if (velocityTracker == null || !isExpanding ||
+ event.actionMasked == MotionEvent.ACTION_DOWN) {
return startExpansion(event)
}
velocityTracker!!.addMovement(event)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 6a3302473e63..382715a3fb77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -293,7 +293,7 @@ public class ActivityLaunchAnimator {
.withCornerRadius(mCornerRadius)
.withVisibility(true)
.build();
- mSyncRtTransactionApplier.scheduleApply(true /* earlyWakeup */, params);
+ mSyncRtTransactionApplier.scheduleApply(params);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
index 5ee4693a32bf..e0532c3e2b28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -17,9 +17,11 @@
package com.android.systemui.statusbar.notification;
import android.content.res.Resources;
+import android.text.Layout;
import android.util.Pools;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import com.android.internal.widget.IMessagingLayout;
import com.android.internal.widget.MessagingGroup;
@@ -229,6 +231,15 @@ public class MessagingLayoutTransformState extends TransformState {
return result;
}
+ private boolean hasEllipses(TextView textView) {
+ Layout layout = textView.getLayout();
+ return layout != null && layout.getEllipsisCount(layout.getLineCount() - 1) > 0;
+ }
+
+ private boolean needsReflow(TextView own, TextView other) {
+ return hasEllipses(own) != hasEllipses(other);
+ }
+
/**
* Transform two groups towards each other.
*
@@ -238,13 +249,20 @@ public class MessagingLayoutTransformState extends TransformState {
float transformationAmount, boolean to) {
boolean useLinearTransformation =
otherGroup.getIsolatedMessage() == null && !mTransformInfo.isAnimating();
- transformView(transformationAmount, to, ownGroup.getSenderView(), otherGroup.getSenderView(),
- true /* sameAsAny */, useLinearTransformation);
+ TextView ownSenderView = ownGroup.getSenderView();
+ TextView otherSenderView = otherGroup.getSenderView();
+ transformView(transformationAmount, to, ownSenderView, otherSenderView,
+ // Normally this would be handled by the TextViewMessageState#sameAs check, but in
+ // this case it doesn't work because our text won't match, due to the appended colon
+ // in the collapsed view.
+ !needsReflow(ownSenderView, otherSenderView),
+ useLinearTransformation);
int totalAvatarTranslation = transformView(transformationAmount, to, ownGroup.getAvatar(),
otherGroup.getAvatar(), true /* sameAsAny */, useLinearTransformation);
List<MessagingMessage> ownMessages = ownGroup.getMessages();
List<MessagingMessage> otherMessages = otherGroup.getMessages();
float previousTranslation = 0;
+ boolean isLastView = true;
for (int i = 0; i < ownMessages.size(); i++) {
View child = ownMessages.get(ownMessages.size() - 1 - i).getView();
if (isGone(child)) {
@@ -278,6 +296,9 @@ public class MessagingLayoutTransformState extends TransformState {
mMessagingLayout.setMessagingClippingDisabled(true);
}
if (otherChild == null) {
+ if (isLastView) {
+ previousTranslation = ownSenderView.getTranslationY();
+ }
child.setTranslationY(previousTranslation);
setClippingDeactivated(child, true);
} else if (ownGroup.getIsolatedMessage() == child || otherIsIsolated) {
@@ -287,6 +308,7 @@ public class MessagingLayoutTransformState extends TransformState {
} else {
previousTranslation = child.getTranslationY();
}
+ isLastView = false;
}
ownGroup.updateClipRect();
return totalAvatarTranslation;
@@ -382,6 +404,9 @@ public class MessagingLayoutTransformState extends TransformState {
if (view.getParent() == null) {
return true;
}
+ if (view.getWidth() == 0) {
+ return true;
+ }
final ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp instanceof MessagingLinearLayout.LayoutParams
&& ((MessagingLinearLayout.LayoutParams) lp).hide) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index b5b756d6ed9b..4b244bb18975 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -39,8 +39,8 @@ import javax.inject.Inject;
import javax.inject.Singleton;
/**
- * Handles ForegroundService interactions with notifications.
- * Tags notifications with appOps.
+ * Handles ForegroundService and AppOp interactions with notifications.
+ * Tags notifications with appOps
* Lifetime extends notifications associated with an ongoing ForegroundService.
* Filters out notifications that represent foreground services that are no longer running
*
@@ -48,12 +48,10 @@ import javax.inject.Singleton;
* frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceController
* frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener
* frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender
- *
- * TODO: AppOps stuff should be spun off into its own coordinator
*/
@Singleton
-public class ForegroundCoordinator implements Coordinator {
- private static final String TAG = "ForegroundCoordinator";
+public class AppOpsCoordinator implements Coordinator {
+ private static final String TAG = "AppOpsCoordinator";
private final ForegroundServiceController mForegroundServiceController;
private final AppOpsController mAppOpsController;
@@ -62,7 +60,7 @@ public class ForegroundCoordinator implements Coordinator {
private NotifPipeline mNotifPipeline;
@Inject
- public ForegroundCoordinator(
+ public AppOpsCoordinator(
ForegroundServiceController foregroundServiceController,
AppOpsController appOpsController,
@Main DelayableExecutor mainExecutor) {
@@ -89,18 +87,22 @@ public class ForegroundCoordinator implements Coordinator {
}
/**
- * Filters out notifications that represent foreground services that are no longer running.
+ * Filters out notifications that represent foreground services that are no longer running or
+ * that already have an app notification with the appOps tagged to
*/
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
@Override
public boolean shouldFilterOut(NotificationEntry entry, long now) {
StatusBarNotification sbn = entry.getSbn();
+
+ // Filters out system-posted disclosure notifications when unneeded
if (mForegroundServiceController.isDisclosureNotification(sbn)
&& !mForegroundServiceController.isDisclosureNeededForUser(
sbn.getUser().getIdentifier())) {
return true;
}
+ // Filters out system alert notifications when unneeded
if (mForegroundServiceController.isSystemAlertNotification(sbn)) {
final String[] apps = sbn.getNotification().extras.getStringArray(
Notification.EXTRA_FOREGROUND_APPS);
@@ -179,23 +181,24 @@ public class ForegroundCoordinator implements Coordinator {
private NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
@Override
public void onEntryAdded(NotificationEntry entry) {
- tagForeground(entry);
+ tagAppOps(entry);
}
@Override
public void onEntryUpdated(NotificationEntry entry) {
- tagForeground(entry);
+ tagAppOps(entry);
}
- private void tagForeground(NotificationEntry entry) {
+ private void tagAppOps(NotificationEntry entry) {
final StatusBarNotification sbn = entry.getSbn();
// note: requires that the ForegroundServiceController is updating their appOps first
ArraySet<Integer> activeOps =
mForegroundServiceController.getAppOps(
sbn.getUser().getIdentifier(),
sbn.getPackageName());
+
+ entry.mActiveAppOps.clear();
if (activeOps != null) {
- entry.mActiveAppOps.clear();
entry.mActiveAppOps.addAll(activeOps);
}
}
@@ -218,24 +221,26 @@ public class ForegroundCoordinator implements Coordinator {
int userId = UserHandle.getUserId(uid);
- // Update appOp if there's an associated posted notification:
- final String foregroundKey = mForegroundServiceController.getStandardLayoutKey(userId,
- packageName);
- if (foregroundKey != null) {
- final NotificationEntry entry = findNotificationEntryWithKey(foregroundKey);
- if (entry != null
- && uid == entry.getSbn().getUid()
- && packageName.equals(entry.getSbn().getPackageName())) {
- boolean changed;
- if (active) {
- changed = entry.mActiveAppOps.add(code);
- } else {
- changed = entry.mActiveAppOps.remove(code);
- }
- if (changed) {
- mNotifFilter.invalidateList();
+ // Update appOps of the app's posted notifications with standard layouts
+ final ArraySet<String> notifKeys =
+ mForegroundServiceController.getStandardLayoutKeys(userId, packageName);
+ if (notifKeys != null) {
+ boolean changed = false;
+ for (int i = 0; i < notifKeys.size(); i++) {
+ final NotificationEntry entry = findNotificationEntryWithKey(notifKeys.valueAt(i));
+ if (entry != null
+ && uid == entry.getSbn().getUid()
+ && packageName.equals(entry.getSbn().getPackageName())) {
+ if (active) {
+ changed |= entry.mActiveAppOps.add(code);
+ } else {
+ changed |= entry.mActiveAppOps.remove(code);
+ }
}
}
+ if (changed) {
+ mNotifFilter.invalidateList();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
index 261ae079a2c8..e595dd4a2f71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
@@ -39,11 +39,14 @@ import javax.inject.Inject;
*/
public class HideNotifsForOtherUsersCoordinator implements Coordinator {
private final NotificationLockscreenUserManager mLockscreenUserManager;
+ private final SharedCoordinatorLogger mLogger;
@Inject
public HideNotifsForOtherUsersCoordinator(
- NotificationLockscreenUserManager lockscreenUserManager) {
+ NotificationLockscreenUserManager lockscreenUserManager,
+ SharedCoordinatorLogger logger) {
mLockscreenUserManager = lockscreenUserManager;
+ mLogger = logger;
}
@Override
@@ -61,9 +64,27 @@ public class HideNotifsForOtherUsersCoordinator implements Coordinator {
};
private final UserChangedListener mUserChangedListener = new UserChangedListener() {
+ // This listener is fired both when the list of profiles changes and when the current user
+ // changes
@Override
public void onCurrentProfilesChanged(SparseArray<UserInfo> currentProfiles) {
+ mLogger.logUserOrProfileChanged(
+ mLockscreenUserManager.getCurrentUserId(),
+ profileIdsToStr(currentProfiles));
mFilter.invalidateList();
}
};
+
+ private String profileIdsToStr(SparseArray<UserInfo> currentProfiles) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ for (int i = 0; i < currentProfiles.size(); i++) {
+ sb.append(currentProfiles.keyAt(i));
+ if (i < currentProfiles.size() - 1) {
+ sb.append(",");
+ }
+ }
+ sb.append("}");
+ return sb.toString();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
index ac4296439507..99e822c66a8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -52,7 +52,7 @@ public class NotifCoordinators implements Dumpable {
HideNotifsForOtherUsersCoordinator hideNotifsForOtherUsersCoordinator,
KeyguardCoordinator keyguardCoordinator,
RankingCoordinator rankingCoordinator,
- ForegroundCoordinator foregroundCoordinator,
+ AppOpsCoordinator appOpsCoordinator,
DeviceProvisionedCoordinator deviceProvisionedCoordinator,
BubbleCoordinator bubbleCoordinator,
HeadsUpCoordinator headsUpCoordinator,
@@ -64,7 +64,7 @@ public class NotifCoordinators implements Dumpable {
mCoordinators.add(hideNotifsForOtherUsersCoordinator);
mCoordinators.add(keyguardCoordinator);
mCoordinators.add(rankingCoordinator);
- mCoordinators.add(foregroundCoordinator);
+ mCoordinators.add(appOpsCoordinator);
mCoordinators.add(deviceProvisionedCoordinator);
mCoordinators.add(bubbleCoordinator);
if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
new file mode 100644
index 000000000000..c85fc1efee95
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+/**
+ * Shared logging class for coordinators that don't log enough to merit their own logger.
+ */
+class SharedCoordinatorLogger @Inject constructor(
+ @NotificationLog private val buffer: LogBuffer
+) {
+ fun logUserOrProfileChanged(userId: Int, profiles: String) {
+ buffer.log("NotCurrentUserFilter", LogLevel.INFO, {
+ int1 = userId
+ str1 = profiles
+ }, {
+ "Current user or profiles changed. Current user is $int1; profiles are $str1"
+ })
+ }
+}
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 fc8c8dbba7fd..825919f17661 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -19,6 +19,7 @@ import android.content.res.Resources;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
+import android.os.UserHandle;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -34,6 +35,7 @@ import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
+import com.android.systemui.util.UserAwareController;
import java.util.ArrayList;
import java.util.Objects;
@@ -43,7 +45,7 @@ import javax.inject.Inject;
/**
* Manages which tiles should be automatically added to QS.
*/
-public class AutoTileManager {
+public class AutoTileManager implements UserAwareController {
private static final String TAG = "AutoTileManager";
public static final String HOTSPOT = "hotspot";
@@ -52,7 +54,9 @@ public class AutoTileManager {
public static final String WORK = "work";
public static final String NIGHT = "night";
public static final String CAST = "cast";
- public static final String SETTING_SEPARATOR = ":";
+ static final String SETTING_SEPARATOR = ":";
+
+ private UserHandle mCurrentUser;
private final Context mContext;
private final QSTileHost mHost;
@@ -66,43 +70,56 @@ public class AutoTileManager {
private final ArrayList<AutoAddSetting> mAutoAddSettingList = new ArrayList<>();
@Inject
- public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
+ public AutoTileManager(Context context, AutoAddTracker.Builder autoAddTrackerBuilder,
+ QSTileHost host,
@Background Handler handler,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
NightDisplayListener nightDisplayListener,
CastController castController) {
- mAutoTracker = autoAddTracker;
mContext = context;
mHost = host;
+ mCurrentUser = mHost.getUserContext().getUser();
+ mAutoTracker = autoAddTrackerBuilder.setUserId(mCurrentUser.getIdentifier()).build();
mHandler = handler;
mHotspotController = hotspotController;
mDataSaverController = dataSaverController;
mManagedProfileController = managedProfileController;
mNightDisplayListener = nightDisplayListener;
mCastController = castController;
+
+ populateSettingsList();
+ startControllersAndSettingsListeners();
+ }
+
+ protected void startControllersAndSettingsListeners() {
if (!mAutoTracker.isAdded(HOTSPOT)) {
- hotspotController.addCallback(mHotspotCallback);
+ mHotspotController.addCallback(mHotspotCallback);
}
if (!mAutoTracker.isAdded(SAVER)) {
- dataSaverController.addCallback(mDataSaverListener);
+ mDataSaverController.addCallback(mDataSaverListener);
}
if (!mAutoTracker.isAdded(WORK)) {
- managedProfileController.addCallback(mProfileCallback);
+ mManagedProfileController.addCallback(mProfileCallback);
}
if (!mAutoTracker.isAdded(NIGHT)
&& ColorDisplayManager.isNightDisplayAvailable(mContext)) {
- nightDisplayListener.setCallback(mNightDisplayCallback);
+ mNightDisplayListener.setCallback(mNightDisplayCallback);
}
if (!mAutoTracker.isAdded(CAST)) {
- castController.addCallback(mCastCallback);
+ mCastController.addCallback(mCastCallback);
+ }
+
+ int settingsN = mAutoAddSettingList.size();
+ for (int i = 0; i < settingsN; i++) {
+ if (!mAutoTracker.isAdded(mAutoAddSettingList.get(i).mSpec)) {
+ mAutoAddSettingList.get(i).setListening(true);
+ }
}
- populateSettingsList();
}
- public void destroy() {
- mAutoTracker.destroy();
+ protected void stopListening() {
mHotspotController.removeCallback(mHotspotCallback);
mDataSaverController.removeCallback(mDataSaverListener);
mManagedProfileController.removeCallback(mProfileCallback);
@@ -116,6 +133,11 @@ public class AutoTileManager {
}
}
+ public void destroy() {
+ stopListening();
+ mAutoTracker.destroy();
+ }
+
/**
* Populates a list with the pairs setting:spec in the config resource.
* <p>
@@ -137,17 +159,39 @@ public class AutoTileManager {
if (split.length == 2) {
String setting = split[0];
String spec = split[1];
- if (!mAutoTracker.isAdded(spec)) {
- AutoAddSetting s = new AutoAddSetting(mContext, mHandler, setting, spec);
- mAutoAddSettingList.add(s);
- s.setListening(true);
- }
+ // Populate all the settings. As they may not have been added in other users
+ AutoAddSetting s = new AutoAddSetting(mContext, mHandler, setting, spec);
+ mAutoAddSettingList.add(s);
} else {
Log.w(TAG, "Malformed item in array: " + tile);
}
}
}
+ @Override
+ public void changeUser(UserHandle newUser) {
+ if (!Thread.currentThread().equals(mHandler.getLooper().getThread())) {
+ mHandler.post(() -> changeUser(newUser));
+ return;
+ }
+ if (newUser.getIdentifier() == mCurrentUser.getIdentifier()) {
+ return;
+ }
+ stopListening();
+ mCurrentUser = newUser;
+ int settingsN = mAutoAddSettingList.size();
+ for (int i = 0; i < settingsN; i++) {
+ mAutoAddSettingList.get(i).setUserId(newUser.getIdentifier());
+ }
+ mAutoTracker.changeUser(newUser);
+ startControllersAndSettingsListeners();
+ }
+
+ @Override
+ public int getCurrentUserId() {
+ return mCurrentUser.getIdentifier();
+ }
+
public void unmarkTileAsAutoAdded(String tabSpec) {
mAutoTracker.setTileRemoved(tabSpec);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 978394ca05ab..cad1c91975bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -17,7 +17,11 @@ package com.android.systemui.statusbar.phone;
import static android.view.Display.INVALID_DISPLAY;
+import android.app.ActivityManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.PixelFormat;
@@ -75,6 +79,8 @@ import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Executor;
/**
@@ -121,9 +127,18 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
}
};
+ private TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+ @Override
+ public void onTaskStackChanged() {
+ mGestureBlockingActivityRunning = isGestureBlockingActivityRunning();
+ }
+ };
+
private final Context mContext;
private final OverviewProxyService mOverviewProxyService;
- private PluginManager mPluginManager;
+ private final PluginManager mPluginManager;
+ // Activities which should not trigger Back gesture.
+ private final List<ComponentName> mGestureBlockingActivities = new ArrayList<>();
private final Point mDisplaySize = new Point();
private final int mDisplayId;
@@ -162,6 +177,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
private boolean mIsEnabled;
private boolean mIsNavBarShownTransiently;
private boolean mIsBackGestureAllowed;
+ private boolean mGestureBlockingActivityRunning;
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
@@ -203,6 +219,29 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
mMainExecutor = context.getMainExecutor();
mOverviewProxyService = overviewProxyService;
mPluginManager = pluginManager;
+ ComponentName recentsComponentName = ComponentName.unflattenFromString(
+ context.getString(com.android.internal.R.string.config_recentsComponentName));
+ if (recentsComponentName != null) {
+ String recentsPackageName = recentsComponentName.getPackageName();
+ PackageManager manager = context.getPackageManager();
+ try {
+ Resources resources = manager.getResourcesForApplication(recentsPackageName);
+ int resId = resources.getIdentifier(
+ "gesture_blocking_activities", "array", recentsPackageName);
+
+ if (resId == 0) {
+ Log.e(TAG, "No resource found for gesture-blocking activities");
+ } else {
+ String[] gestureBlockingActivities = resources.getStringArray(resId);
+ for (String gestureBlockingActivity : gestureBlockingActivities) {
+ mGestureBlockingActivities.add(
+ ComponentName.unflattenFromString(gestureBlockingActivity));
+ }
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Failed to add gesture blocking activities", e);
+ }
+ }
Dependency.get(ProtoTracer.class).add(this);
mLongPressTimeout = Math.min(MAX_LONG_PRESS_TIMEOUT,
@@ -324,6 +363,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
mGestureNavigationSettingsObserver.unregister();
mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
mPluginManager.removePluginListener(this);
+ ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
try {
WindowManagerGlobal.getWindowManagerService()
@@ -338,6 +378,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
updateDisplaySize();
mContext.getSystemService(DisplayManager.class).registerDisplayListener(this,
mContext.getMainThreadHandler());
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
try {
WindowManagerGlobal.getWindowManagerService()
@@ -491,6 +532,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
mLogGesture = false;
mInRejectedExclusion = false;
mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
+ && !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
&& isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
if (mAllowGesture) {
@@ -633,6 +675,13 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
pw.println(" mEdgeWidthRight=" + mEdgeWidthRight);
}
+ private boolean isGestureBlockingActivityRunning() {
+ ActivityManager.RunningTaskInfo runningTask =
+ ActivityManagerWrapper.getInstance().getRunningTask();
+ ComponentName topActivity = runningTask == null ? null : runningTask.topActivity;
+ return topActivity != null && mGestureBlockingActivities.contains(topActivity);
+ }
+
@Override
public void writeToProto(SystemUiTraceProto proto) {
if (proto.edgeBackGestureHandler == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 83d398d3e7ae..0d6597f1b11b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -39,7 +39,7 @@ import javax.inject.Singleton;
public class LockscreenGestureLogger {
/**
- * Contains Lockscreen related Westworld UiEvent enums.
+ * Contains Lockscreen related statsd UiEvent enums.
*/
public enum LockscreenUiEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "Lockscreen > Pull shade open")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 4821d8c46ed4..e83b159c4911 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -822,7 +822,7 @@ public class NavigationBarView extends FrameLayout implements
*/
public void updateSlippery() {
setSlippery(!isQuickStepSwipeUpEnabled() ||
- (mPanelView.isFullyExpanded() && !mPanelView.isCollapsing()));
+ (mPanelView != null && mPanelView.isFullyExpanded() && !mPanelView.isCollapsing()));
}
private void setSlippery(boolean slippery) {
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 a065b74bda99..06d35a36e3c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -38,6 +38,7 @@ import android.service.notification.ZenModeConfig;
import android.telecom.TelecomManager;
import android.text.format.DateFormat;
import android.util.Log;
+import android.view.View;
import androidx.lifecycle.Observer;
@@ -677,12 +678,18 @@ public class PhoneStatusBarPolicy
}
mIconController.setIcon(mSlotScreenRecord, resourceId, description);
mIconController.setIconVisibility(mSlotScreenRecord, true);
+ // Set as assertive so talkback will announce the countdown
+ mIconController.setIconAccessibilityLiveRegion(mSlotScreenRecord,
+ View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE);
}
@Override
public void onCountdownEnd() {
if (DEBUG) Log.d(TAG, "screenrecord: hiding icon during countdown");
mHandler.post(() -> mIconController.setIconVisibility(mSlotScreenRecord, false));
+ // Reset talkback priority
+ mIconController.setIconAccessibilityLiveRegion(mSlotScreenRecord,
+ View.ACCESSIBILITY_LIVE_REGION_NONE);
}
@Override
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 00eab952c504..60fc17d9474a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -113,6 +113,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
* Scrim opacity when the phone is about to wake-up.
*/
public static final float WAKE_SENSOR_SCRIM_ALPHA = 0.6f;
+
+ /**
+ * Scrim opacity when bubbles are expanded.
+ */
+ public static final float BUBBLE_SCRIM_ALPHA = 0.6f;
+
/**
* The default scrim under the shade and dialogs.
* This should not be lower than 0.54, otherwise we won't pass GAR.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index ade642c5ea9a..2db36f4a62f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -235,7 +235,7 @@ public enum ScrimState {
mFrontAlpha = 0f;
mBehindAlpha = mDefaultScrimAlpha;
- mBubbleAlpha = mDefaultScrimAlpha;
+ mBubbleAlpha = ScrimController.BUBBLE_SCRIM_ALPHA;
mAnimationDuration = ScrimController.ANIMATION_DURATION;
mBlankScreen = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 75da5d123972..93df14f18fda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -67,6 +67,15 @@ public interface StatusBarIconController {
public void setSignalIcon(String slot, WifiIconState state);
public void setMobileIcons(String slot, List<MobileIconState> states);
public void setIconVisibility(String slot, boolean b);
+
+ /**
+ * Sets the live region mode for the icon
+ * @see android.view.View#setAccessibilityLiveRegion(int)
+ * @param slot Icon slot to set region for
+ * @param accessibilityLiveRegion live region mode for the icon
+ */
+ void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion);
+
/**
* If you don't know what to pass for `tag`, either remove all icons for slot, or use
* TAG_PRIMARY to refer to the first icon at a given slot.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index bfcbceaef9af..d0e806769f14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -265,6 +265,22 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
handleSet(index, holder);
}
+ @Override
+ public void setIconAccessibilityLiveRegion(String slotName, int accessibilityLiveRegion) {
+ Slot slot = getSlot(slotName);
+ if (!slot.hasIconsInSlot()) {
+ return;
+ }
+
+ int slotIndex = getSlotIndex(slotName);
+ List<StatusBarIconHolder> iconsToUpdate = slot.getHolderListInViewOrder();
+ for (StatusBarIconHolder holder : iconsToUpdate) {
+ int viewIndex = getViewIndex(slotIndex, holder.getTag());
+ mIconGroups.forEach(l -> l.mGroup.getChildAt(viewIndex)
+ .setAccessibilityLiveRegion(accessibilityLiveRegion));
+ }
+ }
+
public void removeIcon(String slot) {
removeAllIconsForSlot(slot);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index 1fb9b691d525..79d264ca4577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -24,6 +24,8 @@ public interface SecurityController extends CallbackController<SecurityControlle
boolean isDeviceManaged();
boolean hasProfileOwner();
boolean hasWorkProfile();
+ /** Whether this device is organization-owned with a work profile **/
+ boolean isProfileOwnerOfOrganizationOwnedDevice();
String getDeviceOwnerName();
String getProfileOwnerName();
CharSequence getDeviceOwnerOrganizationName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index d29f4fcd0c26..309d4b04ebbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -207,6 +207,11 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
}
@Override
+ public boolean isProfileOwnerOfOrganizationOwnedDevice() {
+ return mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile();
+ }
+
+ @Override
public String getWorkProfileVpnName() {
final int profileId = getWorkProfileUserId(mVpnUserId);
if (profileId == UserHandle.USER_NULL) return null;
diff --git a/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt b/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
index 631ea9d61361..ff53a9ff3b0a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
@@ -17,6 +17,8 @@
package com.android.systemui.util
import android.view.ViewGroup
+import com.android.internal.util.IndentingPrintWriter
+import java.io.PrintWriter
/** [Sequence] that yields all of the direct children of this [ViewGroup] */
val ViewGroup.children
@@ -32,4 +34,15 @@ fun <T> Sequence<T>.takeUntil(pred: (T) -> Boolean): Sequence<T> = sequence {
break
}
}
+}
+
+/**
+ * If `this` is an [IndentingPrintWriter], it will process block inside an indentation level.
+ *
+ * If not, this will just process block.
+ */
+inline fun PrintWriter.indentIfPossible(block: PrintWriter.() -> Unit) {
+ if (this is IndentingPrintWriter) increaseIndent()
+ block()
+ if (this is IndentingPrintWriter) decreaseIndent()
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt b/packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt
index d2776d27ae62..693c2708b0f7 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.controls
+package com.android.systemui.util
import android.os.UserHandle
@@ -23,6 +23,8 @@ import android.os.UserHandle
* changes.
*/
interface UserAwareController {
+ @JvmDefault
fun changeUser(newUser: UserHandle) {}
+
val currentUserId: Int
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/FloatProperties.kt b/packages/SystemUI/src/com/android/systemui/util/animation/FloatProperties.kt
index ecd3afd687b3..a284a747da21 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/FloatProperties.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/FloatProperties.kt
@@ -67,6 +67,40 @@ class FloatProperties {
}
/**
+ * Represents the width of a [Rect]. Typically used to animate resizing a Rect horizontally.
+ *
+ * This property's getter returns [Rect.width], and its setter changes the value of
+ * [Rect.right] by adding the animated width value to [Rect.left].
+ */
+ @JvmField
+ val RECT_WIDTH = object : FloatPropertyCompat<Rect>("RectWidth") {
+ override fun getValue(rect: Rect): Float {
+ return rect.width().toFloat()
+ }
+
+ override fun setValue(rect: Rect, value: Float) {
+ rect.right = rect.left + value.toInt()
+ }
+ }
+
+ /**
+ * Represents the height of a [Rect]. Typically used to animate resizing a Rect vertically.
+ *
+ * This property's getter returns [Rect.height], and its setter changes the value of
+ * [Rect.bottom] by adding the animated height value to [Rect.top].
+ */
+ @JvmField
+ val RECT_HEIGHT = object : FloatPropertyCompat<Rect>("RectHeight") {
+ override fun getValue(rect: Rect): Float {
+ return rect.height().toFloat()
+ }
+
+ override fun setValue(rect: Rect, value: Float) {
+ rect.bottom = rect.top + value.toInt()
+ }
+ }
+
+ /**
* Represents the x-coordinate of a [RectF]. Typically used to animate moving a RectF
* horizontally.
*
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 2e0c035b8547..b12224bf583d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -62,22 +62,38 @@ import javax.inject.Inject;
import javax.inject.Singleton;
/**
+ * Suite of tools to periodically inspect the System UI heap and possibly prompt the user to
+ * capture heap dumps and report them. Includes the implementation of the "Dump SysUI Heap"
+ * quick settings tile.
*/
@Singleton
public class GarbageMonitor implements Dumpable {
- private static final boolean LEAK_REPORTING_ENABLED =
- Build.IS_DEBUGGABLE
- && SystemProperties.getBoolean("debug.enable_leak_reporting", false);
- private static final String FORCE_ENABLE_LEAK_REPORTING = "sysui_force_enable_leak_reporting";
+ // Feature switches
+ // ================
- private static final boolean HEAP_TRACKING_ENABLED = Build.IS_DEBUGGABLE;
+ // Whether to use TrackedGarbage to trigger LeakReporter. Off by default unless you set the
+ // appropriate sysprop on a userdebug device.
+ public static final boolean LEAK_REPORTING_ENABLED = Build.IS_DEBUGGABLE
+ && SystemProperties.getBoolean("debug.enable_leak_reporting", false);
+ public static final String FORCE_ENABLE_LEAK_REPORTING = "sysui_force_enable_leak_reporting";
- // whether to use ActivityManager.setHeapLimit
- private static final boolean ENABLE_AM_HEAP_LIMIT = Build.IS_DEBUGGABLE;
- // heap limit value, in KB (overrides R.integer.watch_heap_limit)
- private static final String SETTINGS_KEY_AM_HEAP_LIMIT = "systemui_am_heap_limit";
+ // Heap tracking: watch the current memory levels and update the MemoryTile if available.
+ // On for all userdebug devices.
+ public static final boolean HEAP_TRACKING_ENABLED = Build.IS_DEBUGGABLE;
- private static final String TAG = "GarbageMonitor";
+ // Tell QSTileHost.java to toss this into the default tileset?
+ public static final boolean ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS = true;
+
+ // whether to use ActivityManager.setHeapLimit (and post a notification to the user asking
+ // to dump the heap). Off by default unless you set the appropriate sysprop on userdebug
+ private static final boolean ENABLE_AM_HEAP_LIMIT = Build.IS_DEBUGGABLE
+ && SystemProperties.getBoolean("debug.enable_sysui_heap_limit", false);
+
+ // Tuning params
+ // =============
+
+ // threshold for setHeapLimit(), in KB (overrides R.integer.watch_heap_limit)
+ private static final String SETTINGS_KEY_AM_HEAP_LIMIT = "systemui_am_heap_limit";
private static final long GARBAGE_INSPECTION_INTERVAL =
15 * DateUtils.MINUTE_IN_MILLIS; // 15 min
@@ -89,6 +105,7 @@ public class GarbageMonitor implements Dumpable {
private static final int GARBAGE_ALLOWANCE = 5;
+ private static final String TAG = "GarbageMonitor";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final Handler mHandler;
@@ -378,9 +395,6 @@ public class GarbageMonitor implements Dumpable {
public static class MemoryTile extends QSTileImpl<QSTile.State> {
public static final String TILE_SPEC = "dbg:mem";
- // Tell QSTileHost.java to toss this into the default tileset?
- public static final boolean ADD_TO_DEFAULT_ON_DEBUGGABLE_BUILDS = true;
-
private final GarbageMonitor gm;
private final ActivityStarter mActivityStarter;
private ProcessMemInfo pmi;
diff --git a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
index 5a2b064c5389..f441049feefb 100644
--- a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
@@ -178,6 +178,18 @@ abstract class MagnetizedObject<T : Any>(
var physicsAnimatorEndListener: PhysicsAnimator.EndListener<T>? = null
/**
+ * Method that is called when the object should be animated stuck to the target. The default
+ * implementation uses the object's x and y properties to animate the object centered inside the
+ * target. You can override this if you need custom animation.
+ *
+ * The method is invoked with the MagneticTarget that the object is sticking to, the X and Y
+ * velocities of the gesture that brought the object into the magnetic radius, whether or not it
+ * was flung, and a callback you must call after your animation completes.
+ */
+ var animateStuckToTarget: (MagneticTarget, Float, Float, Boolean, (() -> Unit)?) -> Unit =
+ ::animateStuckToTargetInternal
+
+ /**
* Sets whether forcefully flinging the object vertically towards a target causes it to be
* attracted to the target and then released immediately, despite never being dragged within the
* magnetic field.
@@ -229,7 +241,7 @@ abstract class MagnetizedObject<T : Any>(
* to the target. If this velocity is reached, the object will be freed even if it wasn't moved
* outside the magnetic field radius.
*/
- var flingUnstuckFromTargetMinVelocity = 1000f
+ var flingUnstuckFromTargetMinVelocity = 4000f
/**
* Sets the maximum X velocity above which the object will not stick to the target. Even if the
@@ -373,7 +385,7 @@ abstract class MagnetizedObject<T : Any>(
targetObjectIsStuckTo = targetObjectIsInMagneticFieldOf
cancelAnimations()
magnetListener.onStuckToTarget(targetObjectIsInMagneticFieldOf!!)
- animateStuckToTarget(targetObjectIsInMagneticFieldOf, velX, velY, false)
+ animateStuckToTarget(targetObjectIsInMagneticFieldOf, velX, velY, false, null)
vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
} else if (targetObjectIsInMagneticFieldOf == null && objectStuckToTarget) {
@@ -402,9 +414,10 @@ abstract class MagnetizedObject<T : Any>(
cancelAnimations()
if (objectStuckToTarget) {
- if (hypot(velX, velY) > flingUnstuckFromTargetMinVelocity) {
- // If the object is stuck, but it was forcefully flung away from the target,
- // tell the listener so the object can be animated out of the target.
+ if (-velY > flingUnstuckFromTargetMinVelocity) {
+ // If the object is stuck, but it was forcefully flung away from the target in
+ // the upward direction, tell the listener so the object can be animated out of
+ // the target.
magnetListener.onUnstuckFromTarget(
targetObjectIsStuckTo!!, velX, velY, wasFlungOut = true)
} else {
@@ -430,8 +443,8 @@ abstract class MagnetizedObject<T : Any>(
targetObjectIsStuckTo = flungToTarget
animateStuckToTarget(flungToTarget, velX, velY, true) {
- targetObjectIsStuckTo = null
magnetListener.onReleasedInTarget(flungToTarget)
+ targetObjectIsStuckTo = null
vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
}
@@ -465,7 +478,7 @@ abstract class MagnetizedObject<T : Any>(
}
/** Animates sticking the object to the provided target with the given start velocities. */
- private fun animateStuckToTarget(
+ private fun animateStuckToTargetInternal(
target: MagneticTarget,
velX: Float,
velY: Float,
@@ -581,10 +594,10 @@ abstract class MagnetizedObject<T : Any>(
* multiple objects.
*/
class MagneticTarget(
- internal val targetView: View,
+ val targetView: View,
var magneticFieldRadiusPx: Int
) {
- internal val centerOnScreen = PointF()
+ val centerOnScreen = PointF()
private val tempLoc = IntArray(2)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index 6131e3b504af..369552fc814d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -340,7 +340,7 @@ public class Events {
}
/**
- * Logs an event to the event log and UiEvent (Westworld) logging. Compare writeEvent, which
+ * Logs an event to the event log and UiEvent (statsd) logging. Compare writeEvent, which
* adds more log destinations.
* @param tag One of the EVENT_* codes above.
* @param list Any additional event-specific arguments, documented above.
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 023879926563..7bc453ac9aa1 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -452,6 +452,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
@Test
+ public void requiresAuthentication_whenEncryptedKeyguard_andBypass() {
+ testStrongAuthExceptOnBouncer(
+ KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
+ }
+
+ @Test
public void requiresAuthentication_whenTimeoutKeyguard_andBypass() {
testStrongAuthExceptOnBouncer(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
@@ -507,20 +513,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void testIgnoresAuth_whenLockdown() {
- testIgnoresAuth(
- KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- }
-
- @Test
- public void testIgnoresAuth_whenEncrypted() {
- testIgnoresAuth(
- KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
- }
-
- private void testIgnoresAuth(int strongAuth) {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
- when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
+ when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
+ KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 805254cda175..60f0cd9da5f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -406,60 +406,76 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
}
@Test
- public void testStdLayoutBasic() {
- final String PKG1 = "com.example.app0";
-
- StatusBarNotification sbn_user1_app1 = makeMockFgSBN(USERID_ONE, PKG1, 0, true);
- sbn_user1_app1.getNotification().flags = 0;
- StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1, 1, true);
- entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_MIN); // not fg
- assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required!
- entryAdded(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN);
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // app1 has got it covered
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, "otherpkg"));
- // let's take out the non-fg notification and see what happens.
- entryRemoved(sbn_user1_app1);
- // still covered by sbn_user1_app1_fg
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1));
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, "anyPkg"));
+ public void testNoNotifsNorAppOps_noSystemAlertWarningRequired() {
+ // no notifications nor app op signals that this package/userId requires system alert
+ // warning
+ assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, "any"));
+ }
- // let's attempt to downgrade the notification from FLAG_FOREGROUND and see what we get
- StatusBarNotification sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1, 1, true);
- sbn_user1_app1_fg_sneaky.getNotification().flags = 0;
- entryUpdated(sbn_user1_app1_fg_sneaky, NotificationManager.IMPORTANCE_MIN);
- assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required!
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, "anything"));
- // ok, ok, we'll put it back
- sbn_user1_app1_fg_sneaky.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
- entryUpdated(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN);
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1));
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, "whatever"));
+ @Test
+ public void testCustomLayouts_systemAlertWarningRequired() {
+ // GIVEN a notification with a custom layout
+ final String pkg = "com.example.app0";
+ StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0,
+ false);
+
+ // WHEN the custom layout entry is added
+ entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN);
+
+ // THEN a system alert warning is required since there aren't any notifications that can
+ // display the app ops
+ assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
+ }
- entryRemoved(sbn_user1_app1_fg_sneaky);
- assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required!
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, "a"));
-
- // let's try a custom layout
- sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1, 1, false);
- entryUpdated(sbn_user1_app1_fg_sneaky, NotificationManager.IMPORTANCE_MIN);
- assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1)); // should be required!
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, "anything"));
- // now let's test an upgrade (non fg to fg)
- entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_MIN);
- assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1));
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, "b"));
- sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
- entryUpdated(sbn_user1_app1,
- NotificationManager.IMPORTANCE_MIN); // this is now a fg notification
+ @Test
+ public void testStandardLayoutExists_noSystemAlertWarningRequired() {
+ // GIVEN two notifications (one with a custom layout, the other with a standard layout)
+ final String pkg = "com.example.app0";
+ StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0,
+ false);
+ StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true);
+
+ // WHEN the entries are added
+ entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN);
+ entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN);
+
+ // THEN no system alert warning is required, since there is at least one notification
+ // with a standard layout that can display the app ops on the notification
+ assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
+ }
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, PKG1));
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1));
+ @Test
+ public void testStandardLayoutRemoved_systemAlertWarningRequired() {
+ // GIVEN two notifications (one with a custom layout, the other with a standard layout)
+ final String pkg = "com.example.app0";
+ StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0,
+ false);
+ StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true);
+
+ // WHEN the entries are added and then the standard layout notification is removed
+ entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN);
+ entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN);
+ entryRemoved(standardLayoutNotif);
+
+ // THEN a system alert warning is required since there aren't any notifications that can
+ // display the app ops
+ assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
+ }
- // remove it, make sure we're out of compliance again
- entryRemoved(sbn_user1_app1); // was fg, should return true
- entryRemoved(sbn_user1_app1);
- assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_TWO, PKG1));
- assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1));
+ @Test
+ public void testStandardLayoutUpdatedToCustomLayout_systemAlertWarningRequired() {
+ // GIVEN a standard layout notification and then an updated version with a customLayout
+ final String pkg = "com.example.app0";
+ StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true);
+ StatusBarNotification updatedToCustomLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, false);
+
+ // WHEN the entries is added and then updated to a custom layout
+ entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN);
+ entryUpdated(updatedToCustomLayoutNotif, NotificationManager.IMPORTANCE_MIN);
+
+ // THEN a system alert warning is required since there aren't any notifications that can
+ // display the app ops
+ assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
}
private StatusBarNotification makeMockSBN(int userId, String pkg, int id, String tag,
@@ -483,6 +499,19 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
return sbn;
}
+ private StatusBarNotification makeMockSBN(int uid, String pkg, int id,
+ boolean usesStdLayout) {
+ StatusBarNotification sbn = makeMockSBN(uid, pkg, id, "foo", 0);
+ if (usesStdLayout) {
+ sbn.getNotification().contentView = null;
+ sbn.getNotification().headsUpContentView = null;
+ sbn.getNotification().bigContentView = null;
+ } else {
+ sbn.getNotification().contentView = mock(RemoteViews.class);
+ }
+ return sbn;
+ }
+
private StatusBarNotification makeMockFgSBN(int uid, String pkg, int id,
boolean usesStdLayout) {
StatusBarNotification sbn =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 713aef9e8a91..dd3a7858fd1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -49,6 +49,7 @@ import org.junit.Rule;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
import java.util.concurrent.Future;
/**
@@ -74,7 +75,8 @@ public abstract class SysuiTestCase {
SystemUIFactory.createFromConfig(mContext);
mDependency = new TestableDependency(mContext);
mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Looper.class),
- mock(DumpManager.class), mock(BroadcastDispatcherLogger.class));
+ mock(Executor.class), mock(DumpManager.class),
+ mock(BroadcastDispatcherLogger.class));
mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
Instrumentation inst = spy(mRealInstrumentation);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
new file mode 100644
index 000000000000..e95eb4ef6509
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.broadcast
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.UserHandle
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import java.lang.IllegalArgumentException
+import java.lang.IllegalStateException
+import java.util.concurrent.Executor
+
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+@SmallTest
+class ActionReceiverTest : SysuiTestCase() {
+
+ companion object {
+ private const val ACTION1 = "TEST_ACTION1"
+ private const val ACTION2 = "TEST_ACTION2"
+ private const val CATEGORY = "TEST_CATEGORY"
+ private val USER = UserHandle.of(0)
+ private fun <T : Any> sameNotNull(arg: T): T = Mockito.same(arg) ?: arg
+
+ fun IntentFilter.matchesOther(it: IntentFilter): Boolean {
+ val actions = actionsIterator()?.asSequence()?.toSet() ?: emptySet()
+ val categories = categoriesIterator()?.asSequence()?.toSet() ?: emptySet()
+ return (it.actionsIterator()?.asSequence()?.toSet() ?: emptySet()) == actions &&
+ (it.categoriesIterator()?.asSequence()?.toSet() ?: emptySet()) == categories &&
+ it.countDataAuthorities() == 0 &&
+ it.countDataPaths() == 0 &&
+ it.countDataSchemes() == 0 &&
+ it.countDataTypes() == 0 &&
+ it.countMimeGroups() == 0 &&
+ it.priority == 0
+ }
+ }
+
+ @Mock
+ private lateinit var registerFunction: BroadcastReceiver.(IntentFilter) -> Unit
+ @Mock
+ private lateinit var unregisterFunction: BroadcastReceiver.() -> Unit
+ @Mock
+ private lateinit var receiver1: BroadcastReceiver
+ @Mock
+ private lateinit var receiver2: BroadcastReceiver
+ @Mock
+ private lateinit var logger: BroadcastDispatcherLogger
+ @Captor
+ private lateinit var intentFilterCaptor: ArgumentCaptor<IntentFilter>
+
+ private lateinit var executor: FakeExecutor
+ private lateinit var actionReceiver: ActionReceiver
+ private val directExecutor = Executor { it.run() }
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ executor = FakeExecutor(FakeSystemClock())
+
+ actionReceiver = ActionReceiver(
+ ACTION1,
+ USER.identifier,
+ registerFunction,
+ unregisterFunction,
+ executor,
+ logger
+ )
+ }
+
+ @Test
+ fun testStartsUnregistered() {
+ assertFalse(actionReceiver.registered)
+ verify(registerFunction, never()).invoke(sameNotNull(actionReceiver),
+ any(IntentFilter::class.java))
+ }
+
+ @Test
+ fun testRegistersOnFirstAdd() {
+ val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER)
+
+ actionReceiver.addReceiverData(receiverData)
+
+ assertTrue(actionReceiver.registered)
+ verify(registerFunction).invoke(sameNotNull(actionReceiver), capture(intentFilterCaptor))
+
+ assertTrue(IntentFilter(ACTION1).matchesOther(intentFilterCaptor.value))
+ }
+
+ @Test
+ fun testRegistersOnlyOnce() {
+ val receiverData1 = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER)
+ val receiverData2 = ReceiverData(receiver2, IntentFilter(ACTION1), directExecutor, USER)
+
+ actionReceiver.addReceiverData(receiverData1)
+ actionReceiver.addReceiverData(receiverData2)
+
+ verify(registerFunction).invoke(sameNotNull(actionReceiver), any(IntentFilter::class.java))
+ }
+
+ @Test
+ fun testRemovingLastReceiverUnregisters() {
+ val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER)
+
+ actionReceiver.addReceiverData(receiverData)
+
+ actionReceiver.removeReceiver(receiver1)
+
+ assertFalse(actionReceiver.registered)
+ verify(unregisterFunction).invoke(sameNotNull(actionReceiver))
+ }
+
+ @Test
+ fun testRemovingWhileOtherReceiversDoesntUnregister() {
+ val receiverData1 = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER)
+ val receiverData2 = ReceiverData(receiver2, IntentFilter(ACTION1), directExecutor, USER)
+
+ actionReceiver.addReceiverData(receiverData1)
+ actionReceiver.addReceiverData(receiverData2)
+
+ actionReceiver.removeReceiver(receiver1)
+
+ assertTrue(actionReceiver.registered)
+ verify(unregisterFunction, never()).invoke(any(BroadcastReceiver::class.java))
+ }
+
+ @Test
+ fun testReceiverHasCategories() {
+ val filter = IntentFilter(ACTION1)
+ filter.addCategory(CATEGORY)
+
+ val receiverData = ReceiverData(receiver1, filter, directExecutor, USER)
+
+ actionReceiver.addReceiverData(receiverData)
+
+ verify(registerFunction).invoke(sameNotNull(actionReceiver), capture(intentFilterCaptor))
+ assertTrue(intentFilterCaptor.value.hasCategory(CATEGORY))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testNotRegisteredWithWrongAction_throwsException() {
+ val receiverData = ReceiverData(receiver1, IntentFilter(ACTION2), directExecutor, USER)
+
+ actionReceiver.addReceiverData(receiverData)
+ }
+
+ @Test
+ fun testReceiverGetsBroadcast() {
+ val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER)
+ actionReceiver.addReceiverData(receiverData)
+
+ val intent = Intent(ACTION1)
+
+ actionReceiver.onReceive(mContext, intent)
+
+ executor.runAllReady()
+
+ verify(receiver1).onReceive(any(Context::class.java), sameNotNull(intent))
+ }
+
+ @Test
+ fun testReceiverGetsPendingResult() {
+ val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER)
+ actionReceiver.addReceiverData(receiverData)
+
+ val intent = Intent(ACTION1)
+ val pendingResult = mock(BroadcastReceiver.PendingResult::class.java)
+
+ actionReceiver.pendingResult = pendingResult
+ actionReceiver.onReceive(mContext, intent)
+
+ executor.runAllReady()
+ verify(receiver1).pendingResult = pendingResult
+ }
+
+ @Test
+ fun testBroadcastIsDispatchedInExecutor() {
+ val executor = FakeExecutor(FakeSystemClock())
+ val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), executor, USER)
+ actionReceiver.addReceiverData(receiverData)
+
+ val intent = Intent(ACTION1)
+ actionReceiver.onReceive(mContext, intent)
+
+ this.executor.runAllReady()
+
+ verify(receiver1, never()).onReceive(mContext, intent)
+
+ executor.runAllReady()
+ // Dispatched after executor is processed
+ verify(receiver1).onReceive(mContext, intent)
+ }
+
+ @Test
+ fun testBroadcastReceivedDispatched_logger() {
+ val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER)
+
+ actionReceiver.addReceiverData(receiverData)
+
+ val intent = Intent(ACTION1)
+ actionReceiver.onReceive(mContext, intent)
+ verify(logger).logBroadcastReceived(anyInt(), eq(USER.identifier), eq(intent))
+
+ verify(logger, never()).logBroadcastDispatched(anyInt(), anyString(),
+ any(BroadcastReceiver::class.java))
+
+ executor.runAllReady()
+
+ verify(logger).logBroadcastDispatched(anyInt(), eq(ACTION1), sameNotNull(receiver1))
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun testBroadcastWithWrongAction_throwsException() {
+ actionReceiver.onReceive(mContext, Intent(ACTION2))
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
index 4ed284ede634..22e9594ca420 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
@@ -98,6 +98,7 @@ class BroadcastDispatcherTest : SysuiTestCase() {
broadcastDispatcher = TestBroadcastDispatcher(
mockContext,
testableLooper.looper,
+ mock(Executor::class.java),
mock(DumpManager::class.java),
logger,
mapOf(0 to mockUBRUser0, 1 to mockUBRUser1))
@@ -246,10 +247,11 @@ class BroadcastDispatcherTest : SysuiTestCase() {
private class TestBroadcastDispatcher(
context: Context,
bgLooper: Looper,
+ executor: Executor,
dumpManager: DumpManager,
logger: BroadcastDispatcherLogger,
var mockUBRMap: Map<Int, UserBroadcastDispatcher>
- ) : BroadcastDispatcher(context, bgLooper, dumpManager, logger) {
+ ) : BroadcastDispatcher(context, bgLooper, executor, dumpManager, logger) {
override fun createUBRForUser(userId: Int): UserBroadcastDispatcher {
return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
index 09a091689a23..949932da4d50 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
@@ -31,9 +31,10 @@ import java.util.concurrent.Executor
class FakeBroadcastDispatcher(
context: SysuiTestableContext,
looper: Looper,
+ executor: Executor,
dumpManager: DumpManager,
logger: BroadcastDispatcherLogger
-) : BroadcastDispatcher(context, looper, dumpManager, logger) {
+) : BroadcastDispatcher(context, looper, executor, dumpManager, logger) {
private val registeredReceivers = ArraySet<BroadcastReceiver>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
index 443357694f4d..dfe143254788 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
@@ -18,7 +18,6 @@ package com.android.systemui.broadcast
import android.content.BroadcastReceiver
import android.content.Context
-import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import android.os.UserHandle
@@ -29,26 +28,18 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
-import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
-import junit.framework.Assert.assertTrue
+import junit.framework.Assert.assertNotNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
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
import org.mockito.Mockito
-import org.mockito.Mockito.anyString
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.times
+import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import java.util.concurrent.Executor
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
@@ -58,8 +49,6 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
companion object {
private const val ACTION_1 = "com.android.systemui.tests.ACTION_1"
private const val ACTION_2 = "com.android.systemui.tests.ACTION_2"
- private const val CATEGORY_1 = "com.android.systemui.tests.CATEGORY_1"
- private const val CATEGORY_2 = "com.android.systemui.tests.CATEGORY_2"
private const val USER_ID = 0
private val USER_HANDLE = UserHandle.of(USER_ID)
@@ -75,13 +64,8 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
@Mock
private lateinit var mockContext: Context
@Mock
- private lateinit var mPendingResult: BroadcastReceiver.PendingResult
- @Mock
private lateinit var logger: BroadcastDispatcherLogger
- @Captor
- private lateinit var argumentCaptor: ArgumentCaptor<IntentFilter>
-
private lateinit var testableLooper: TestableLooper
private lateinit var userBroadcastDispatcher: UserBroadcastDispatcher
private lateinit var intentFilter: IntentFilter
@@ -96,46 +80,25 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
handler = Handler(testableLooper.looper)
fakeExecutor = FakeExecutor(FakeSystemClock())
- userBroadcastDispatcher = UserBroadcastDispatcher(
- mockContext, USER_ID, testableLooper.looper, logger)
- userBroadcastDispatcher.pendingResult = mPendingResult
- }
-
- @Test
- fun testNotRegisteredOnStart() {
- testableLooper.processAllMessages()
- verify(mockContext, never()).registerReceiver(any(), any())
- verify(mockContext, never()).registerReceiver(any(), any(), anyInt())
- verify(mockContext, never()).registerReceiver(any(), any(), anyString(), any())
- verify(mockContext, never()).registerReceiver(any(), any(), anyString(), any(), anyInt())
- verify(mockContext, never()).registerReceiverAsUser(any(), any(), any(), anyString(), any())
- }
-
- @Test
- fun testNotRegisteredOnStart_logging() {
- testableLooper.processAllMessages()
-
- verify(logger, never()).logContextReceiverRegistered(anyInt(), any())
+ userBroadcastDispatcher = object : UserBroadcastDispatcher(
+ mockContext, USER_ID, testableLooper.looper, mock(Executor::class.java), logger) {
+ override fun createActionReceiver(action: String): ActionReceiver {
+ return mock(ActionReceiver::class.java)
+ }
+ }
}
@Test
fun testSingleReceiverRegistered() {
intentFilter = IntentFilter(ACTION_1)
+ val receiverData = ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
+ userBroadcastDispatcher.registerReceiver(receiverData)
testableLooper.processAllMessages()
- assertTrue(userBroadcastDispatcher.isRegistered())
- verify(mockContext).registerReceiverAsUser(
- any(),
- eq(USER_HANDLE),
- capture(argumentCaptor),
- any(),
- any())
- assertEquals(1, argumentCaptor.value.countActions())
- assertTrue(argumentCaptor.value.hasAction(ACTION_1))
- assertEquals(0, argumentCaptor.value.countCategories())
+ val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1)
+ assertNotNull(actionReceiver)
+ verify(actionReceiver)?.addReceiverData(receiverData)
}
@Test
@@ -147,7 +110,6 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
testableLooper.processAllMessages()
verify(logger).logReceiverRegistered(USER_HANDLE.identifier, broadcastReceiver)
- verify(logger).logContextReceiverRegistered(eq(USER_HANDLE.identifier), any())
}
@Test
@@ -157,16 +119,13 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
testableLooper.processAllMessages()
- reset(mockContext)
-
- assertTrue(userBroadcastDispatcher.isRegistered())
userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
testableLooper.processAllMessages()
- verify(mockContext, atLeastOnce()).unregisterReceiver(any())
- verify(mockContext, never()).registerReceiverAsUser(any(), any(), any(), any(), any())
- assertFalse(userBroadcastDispatcher.isRegistered())
+ val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1)
+ assertNotNull(actionReceiver)
+ verify(actionReceiver)?.removeReceiver(broadcastReceiver)
}
@Test
@@ -181,139 +140,6 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
testableLooper.processAllMessages()
verify(logger).logReceiverUnregistered(USER_HANDLE.identifier, broadcastReceiver)
- verify(logger).logContextReceiverUnregistered(USER_HANDLE.identifier)
- }
-
- @Test
- fun testFilterHasAllActionsAndCategories_twoReceivers() {
- intentFilter = IntentFilter(ACTION_1)
- intentFilterOther = IntentFilter(ACTION_2).apply {
- addCategory(CATEGORY_1)
- addCategory(CATEGORY_2)
- }
-
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE))
-
- testableLooper.processAllMessages()
- assertTrue(userBroadcastDispatcher.isRegistered())
-
- verify(mockContext, times(2)).registerReceiverAsUser(
- any(),
- eq(USER_HANDLE),
- capture(argumentCaptor),
- any(),
- any())
-
- val lastFilter = argumentCaptor.value
-
- assertTrue(lastFilter.hasAction(ACTION_1))
- assertTrue(lastFilter.hasAction(ACTION_2))
- assertTrue(lastFilter.hasCategory(CATEGORY_1))
- assertTrue(lastFilter.hasCategory(CATEGORY_1))
- }
-
- @Test
- fun testDispatchToCorrectReceiver() {
- intentFilter = IntentFilter(ACTION_1)
- intentFilterOther = IntentFilter(ACTION_2)
-
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE))
-
- val intent = Intent(ACTION_2)
-
- userBroadcastDispatcher.onReceive(mockContext, intent)
- testableLooper.processAllMessages()
- fakeExecutor.runAllReady()
-
- verify(broadcastReceiver, never()).onReceive(any(), any())
- verify(broadcastReceiverOther).onReceive(mockContext, intent)
- }
-
- @Test
- fun testDispatch_logger() {
- intentFilter = IntentFilter(ACTION_1)
- intentFilterOther = IntentFilter(ACTION_2)
-
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE))
-
- val intent = Intent(ACTION_2)
-
- userBroadcastDispatcher.onReceive(mockContext, intent)
- testableLooper.processAllMessages()
- fakeExecutor.runAllReady()
-
- val captor = ArgumentCaptor.forClass(Int::class.java)
- verify(logger)
- .logBroadcastReceived(captor.capture(), eq(USER_HANDLE.identifier), eq(intent))
- verify(logger).logBroadcastDispatched(captor.value, ACTION_2, broadcastReceiverOther)
- verify(logger, never())
- .logBroadcastDispatched(eq(captor.value), any(), eq(broadcastReceiver))
- }
-
- @Test
- fun testDispatchToCorrectReceiver_differentFiltersSameReceiver() {
- intentFilter = IntentFilter(ACTION_1)
- intentFilterOther = IntentFilter(ACTION_2)
-
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilterOther, fakeExecutor, USER_HANDLE))
-
- val intent = Intent(ACTION_2)
-
- userBroadcastDispatcher.onReceive(mockContext, intent)
- testableLooper.processAllMessages()
- fakeExecutor.runAllReady()
-
- verify(broadcastReceiver).onReceive(mockContext, intent)
- }
-
- @Test
- fun testDispatchIntentWithoutCategories() {
- intentFilter = IntentFilter(ACTION_1)
- intentFilter.addCategory(CATEGORY_1)
- intentFilterOther = IntentFilter(ACTION_1)
- intentFilterOther.addCategory(CATEGORY_2)
-
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE))
-
- val intent = Intent(ACTION_1)
-
- userBroadcastDispatcher.onReceive(mockContext, intent)
- testableLooper.processAllMessages()
- fakeExecutor.runAllReady()
-
- verify(broadcastReceiver).onReceive(mockContext, intent)
- verify(broadcastReceiverOther).onReceive(mockContext, intent)
- }
-
- @Test
- fun testPendingResult() {
- intentFilter = IntentFilter(ACTION_1)
- userBroadcastDispatcher.registerReceiver(
- ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
-
- val intent = Intent(ACTION_1)
- userBroadcastDispatcher.onReceive(mockContext, intent)
-
- testableLooper.processAllMessages()
- fakeExecutor.runAllReady()
-
- verify(broadcastReceiver).onReceive(mockContext, intent)
- verify(broadcastReceiver).pendingResult = mPendingResult
}
@Test
@@ -333,4 +159,8 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
assertFalse(userBroadcastDispatcher.isReceiverReferenceHeld(broadcastReceiver))
}
+
+ private fun UserBroadcastDispatcher.getActionReceiver(action: String): ActionReceiver? {
+ return actionsToActionsReceivers.get(action)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 59f8c4e329a4..36398a6fc122 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -304,6 +304,10 @@ public class BubbleControllerTest extends SysuiTestCase {
public void testPromoteBubble_autoExpand() throws Exception {
mBubbleController.updateBubble(mRow2.getEntry());
mBubbleController.updateBubble(mRow.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
+ .thenReturn(mRow.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
+ .thenReturn(mRow2.getEntry());
mBubbleController.removeBubble(
mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
@@ -331,6 +335,10 @@ public class BubbleControllerTest extends SysuiTestCase {
mBubbleController.updateBubble(mRow2.getEntry());
mBubbleController.updateBubble(mRow.getEntry(), /* suppressFlyout */
false, /* showInShade */ true);
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
+ .thenReturn(mRow.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
+ .thenReturn(mRow2.getEntry());
mBubbleController.removeBubble(
mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
@@ -433,15 +441,16 @@ public class BubbleControllerTest extends SysuiTestCase {
assertTrue(mSysUiStateBubblesExpanded);
// Last added is the one that is expanded
- assertEquals(mRow2.getEntry(), mBubbleData.getSelectedBubble().getEntry());
+ assertEquals(mRow2.getEntry().getKey(), mBubbleData.getSelectedBubble().getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow2.getEntry()));
// Switch which bubble is expanded
- mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
+ mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(
+ mRow.getEntry().getKey()));
mBubbleData.setExpanded(true);
- assertEquals(mRow.getEntry(),
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
+ assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow.getEntry()));
@@ -543,27 +552,27 @@ public class BubbleControllerTest extends SysuiTestCase {
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
// Last added is the one that is expanded
- assertEquals(mRow2.getEntry(),
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
+ assertEquals(mRow2.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow2.getEntry()));
// Dismiss currently expanded
mBubbleController.removeBubble(
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey())
- .getEntry().getKey(),
+ mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey(),
BubbleController.DISMISS_USER_GESTURE);
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
// Make sure first bubble is selected
- assertEquals(mRow.getEntry(),
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
+ assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey());
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
// Dismiss that one
mBubbleController.removeBubble(
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey())
- .getEntry().getKey(),
+ mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey(),
BubbleController.DISMISS_USER_GESTURE);
// Make sure state changes and collapse happens
@@ -839,6 +848,12 @@ public class BubbleControllerTest extends SysuiTestCase {
mRow2.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
mBubbleController.updateBubble(
mRow3.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
+ .thenReturn(mRow.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
+ .thenReturn(mRow2.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow3.getEntry().getKey()))
+ .thenReturn(mRow3.getEntry());
assertEquals(mBubbleData.getBubbles().size(), 3);
mBubbleData.setMaxOverflowBubbles(1);
@@ -908,6 +923,8 @@ public class BubbleControllerTest extends SysuiTestCase {
// GIVEN a group summary with a bubble child
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
+ when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ .thenReturn(groupedBubble.getEntry());
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
@@ -927,6 +944,8 @@ public class BubbleControllerTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ .thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
@@ -948,6 +967,8 @@ public class BubbleControllerTest extends SysuiTestCase {
// GIVEN a group summary with two (non-bubble) children and one bubble child
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
+ when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ .thenReturn(groupedBubble.getEntry());
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
index 72f816ff56b5..be03923e7264 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
@@ -86,8 +86,7 @@ public class BubbleTest extends SysuiTestCase {
final String msg = "Hello there!";
doReturn(Notification.Style.class).when(mNotif).getNotificationStyle();
mExtras.putCharSequence(Notification.EXTRA_TEXT, msg);
- assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mContext,
- mEntry).message);
+ assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
}
@Test
@@ -98,8 +97,7 @@ public class BubbleTest extends SysuiTestCase {
mExtras.putCharSequence(Notification.EXTRA_BIG_TEXT, msg);
// Should be big text, not the small text.
- assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mContext,
- mEntry).message);
+ assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
}
@Test
@@ -107,8 +105,7 @@ public class BubbleTest extends SysuiTestCase {
doReturn(Notification.MediaStyle.class).when(mNotif).getNotificationStyle();
// Media notifs don't get update messages.
- assertNull(BubbleViewInfoTask.extractFlyoutMessage(mContext,
- mEntry).message);
+ assertNull(BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
}
@Test
@@ -124,7 +121,7 @@ public class BubbleTest extends SysuiTestCase {
// Should be the last one only.
assertEquals("Really? I prefer them that way.",
- BubbleViewInfoTask.extractFlyoutMessage(mContext, mEntry).message);
+ BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
}
@Test
@@ -139,11 +136,8 @@ public class BubbleTest extends SysuiTestCase {
"Oh, hello!", 0, "Mady").toBundle()});
// Should be the last one only.
- assertEquals("Oh, hello!",
- BubbleViewInfoTask.extractFlyoutMessage(mContext, mEntry).message);
- assertEquals("Mady",
- BubbleViewInfoTask.extractFlyoutMessage(mContext,
- mEntry).senderName);
+ assertEquals("Oh, hello!", BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
+ assertEquals("Mady", BubbleViewInfoTask.extractFlyoutMessage(mEntry).senderName);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 58e06b5178c6..1c70db3a548e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -302,6 +302,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
public void testRemoveBubble_withDismissedNotif_notInOverflow() {
mEntryListener.onEntryAdded(mRow.getEntry());
mBubbleController.updateBubble(mRow.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
+ .thenReturn(mRow.getEntry());
assertTrue(mBubbleController.hasBubbles());
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
@@ -388,14 +390,14 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
true, mRow.getEntry().getKey());
// Last added is the one that is expanded
- assertEquals(mRow2.getEntry(), mBubbleData.getSelectedBubble().getEntry());
+ assertEquals(mRow2.getEntry().getKey(), mBubbleData.getSelectedBubble().getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry()));
// Switch which bubble is expanded
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
mBubbleData.setExpanded(true);
- assertEquals(mRow.getEntry(),
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
+ assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow.getEntry()));
@@ -488,27 +490,27 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
// Last added is the one that is expanded
- assertEquals(mRow2.getEntry(),
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
+ assertEquals(mRow2.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow2.getEntry()));
// Dismiss currently expanded
mBubbleController.removeBubble(
mBubbleData.getBubbleInStackWithKey(
- stackView.getExpandedBubble().getKey()).getEntry().getKey(),
+ stackView.getExpandedBubble().getKey()).getKey(),
BubbleController.DISMISS_USER_GESTURE);
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
// Make sure first bubble is selected
- assertEquals(mRow.getEntry(),
- mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
+ assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
+ stackView.getExpandedBubble().getKey()).getKey());
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
// Dismiss that one
mBubbleController.removeBubble(
mBubbleData.getBubbleInStackWithKey(
- stackView.getExpandedBubble().getKey()).getEntry().getKey(),
+ stackView.getExpandedBubble().getKey()).getKey(),
BubbleController.DISMISS_USER_GESTURE);
// Make sure state changes and collapse happens
@@ -767,6 +769,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ .thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
@@ -785,6 +789,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ .thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
@@ -807,6 +813,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
+ when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ .thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
// WHEN the summary is dismissed
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt
index 1d02b8dba910..9b8fd11febe3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt
@@ -32,7 +32,7 @@ class BubblePersistentRepositoryTest : SysuiTestCase() {
private val bubbles = listOf(
BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0),
- BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428),
+ BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title"),
BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0)
)
private lateinit var repository: BubblePersistentRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt
index f9d611c2bb33..7ea611c9c6a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt
@@ -37,9 +37,10 @@ class BubbleVolatileRepositoryTest : SysuiTestCase() {
private val user0 = UserHandle.of(0)
private val user10 = UserHandle.of(10)
- private val bubble1 = BubbleEntity(0, PKG_MESSENGER, "shortcut-1", "k1", 120, 0)
- private val bubble2 = BubbleEntity(10, PKG_CHAT, "alice and bob", "k2", 0, 16537428)
- private val bubble3 = BubbleEntity(0, PKG_MESSENGER, "shortcut-2", "k3", 120, 0)
+ private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0)
+ private val bubble2 = BubbleEntity(10, "com.example.chat", "alice and bob",
+ "key-2", 0, 16537428, "title")
+ private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0)
private val bubbles = listOf(bubble1, bubble2, bubble3)
@@ -101,6 +102,19 @@ class BubbleVolatileRepositoryTest : SysuiTestCase() {
eq(listOf("alice and bob")), eq(user10),
eq(LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS))
}
+
+ @Test
+ fun testAddBubbleMatchesByKey() {
+ val bubble = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, "title")
+ repository.addBubbles(listOf(bubble))
+ assertEquals(bubble, repository.bubbles.get(0))
+
+ // Same key as first bubble but different entry
+ val bubbleModified = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0,
+ "different title")
+ repository.addBubbles(listOf(bubbleModified))
+ assertEquals(bubbleModified, repository.bubbles.get(0))
+ }
}
private const val PKG_MESSENGER = "com.example.messenger"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt
index 49467874dd8b..8cf4534ecdce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt
@@ -31,17 +31,17 @@ import java.io.ByteArrayOutputStream
class BubbleXmlHelperTest : SysuiTestCase() {
private val bubbles = listOf(
- BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0),
- BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428),
- BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0)
+ BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0),
+ BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title"),
+ BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0)
)
@Test
fun testWriteXml() {
val expectedEntries = """
- <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
- <bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" />
- <bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
+<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
""".trimIndent()
ByteArrayOutputStream().use {
writeXml(it, bubbles)
@@ -54,14 +54,29 @@ class BubbleXmlHelperTest : SysuiTestCase() {
@Test
fun testReadXml() {
val src = """
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- <bs>
- <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
- <bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" />
- <bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
- </bs>
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<bs v="1">
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
+<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
+</bs>
""".trimIndent()
val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
assertEquals("failed parsing bubbles from xml\n$src", bubbles, actual)
}
+
+ // TODO: We should handle upgrades gracefully but this is v1
+ @Test
+ fun testUpgradeDropsPreviousData() {
+ val src = """
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<bs>
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
+<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
+<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
+</bs>
+ """.trimIndent()
+ val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
+ assertEquals("failed parsing bubbles from xml\n$src", emptyList<BubbleEntity>(), actual)
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
index 3c1cc232f5c9..e08fe7a13a60 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.globalactions;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
+
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
@@ -34,11 +36,13 @@ import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.ContentResolver;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.Handler;
+import android.os.RemoteException;
import android.os.UserManager;
import android.service.dreams.IDreamManager;
import android.telephony.TelephonyManager;
@@ -424,10 +428,12 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
}
@Test
- public void testShouldShowLockScreenMessage() {
+ public void testShouldShowLockScreenMessage() throws RemoteException {
mGlobalActionsDialog = spy(mGlobalActionsDialog);
mGlobalActionsDialog.mDialog = null;
when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+ when(mActivityManager.getCurrentUser()).thenReturn(newUserInfo());
+ when(mLockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED);
mGlobalActionsDialog.mShowLockScreenCardsAndControls = false;
setupDefaultActions();
when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
@@ -444,10 +450,13 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
}
@Test
- public void testShouldNotShowLockScreenMessage_whenWalletOrControlsShownOnLockScreen() {
+ public void testShouldNotShowLockScreenMessage_whenWalletOrControlsShownOnLockScreen()
+ throws RemoteException {
mGlobalActionsDialog = spy(mGlobalActionsDialog);
mGlobalActionsDialog.mDialog = null;
when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+ when(mActivityManager.getCurrentUser()).thenReturn(newUserInfo());
+ when(mLockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED);
mGlobalActionsDialog.mShowLockScreenCardsAndControls = true;
setupDefaultActions();
when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
@@ -464,10 +473,14 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
}
@Test
- public void testShouldNotShowLockScreenMessage_whenControlsAndWalletBothDisabled() {
+ public void testShouldNotShowLockScreenMessage_whenControlsAndWalletBothDisabled()
+ throws RemoteException {
mGlobalActionsDialog = spy(mGlobalActionsDialog);
mGlobalActionsDialog.mDialog = null;
when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+ when(mActivityManager.getCurrentUser()).thenReturn(newUserInfo());
+ when(mLockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED);
mGlobalActionsDialog.mShowLockScreenCardsAndControls = true;
setupDefaultActions();
when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
@@ -484,6 +497,10 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
}
+ private UserInfo newUserInfo() {
+ return new UserInfo(0, null, null, UserInfo.FLAG_PRIMARY, null);
+ }
+
private void setupDefaultActions() {
String[] actions = {
GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
new file mode 100644
index 000000000000..54520be8a03f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -0,0 +1,126 @@
+package com.android.systemui.media
+
+import android.app.Notification
+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.broadcast.BroadcastDispatcher
+import com.android.systemui.dump.DumpManager
+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.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import java.util.concurrent.Executor
+import org.mockito.Mockito.`when` as whenever
+
+private const val KEY = "KEY"
+private const val PACKAGE_NAME = "com.android.systemui"
+
+private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
+private fun <T> anyObject(): T {
+ return Mockito.anyObject<T>()
+}
+
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidTestingRunner::class)
+class MediaDataManagerTest : SysuiTestCase() {
+
+ @Mock lateinit var mediaControllerFactory: MediaControllerFactory
+ @Mock lateinit var backgroundExecutor: Executor
+ @Mock lateinit var foregroundExecutor: Executor
+ @Mock lateinit var dumpManager: DumpManager
+ @Mock lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock lateinit var mediaTimeoutListener: MediaTimeoutListener
+ @Mock lateinit var mediaResumeListener: MediaResumeListener
+ @JvmField @Rule val mockito = MockitoJUnit.rule()
+ lateinit var mediaDataManager: MediaDataManager
+ lateinit var mediaNotification: StatusBarNotification
+
+ @Before
+ fun setup() {
+ mediaDataManager = MediaDataManager(context, backgroundExecutor, foregroundExecutor,
+ mediaControllerFactory, broadcastDispatcher, dumpManager,
+ mediaTimeoutListener, mediaResumeListener, useMediaResumption = true,
+ useQsMediaPlayer = true)
+ val sbn = mock(StatusBarNotification::class.java)
+ val notification = mock(Notification::class.java)
+ whenever(notification.hasMediaSession()).thenReturn(true)
+ whenever(notification.notificationStyle).thenReturn(Notification.MediaStyle::class.java)
+ whenever(sbn.notification).thenReturn(notification)
+ whenever(sbn.packageName).thenReturn(PACKAGE_NAME)
+ mediaNotification = sbn
+ }
+
+ @After
+ fun tearDown() {
+ mediaDataManager.destroy()
+ }
+
+ @Test
+ fun testHasActiveMedia() {
+ assertThat(mediaDataManager.hasActiveMedia()).isFalse()
+ val data = mock(MediaData::class.java)
+
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = data)
+ assertThat(mediaDataManager.hasActiveMedia()).isFalse()
+
+ whenever(data.active).thenReturn(true)
+ assertThat(mediaDataManager.hasActiveMedia()).isTrue()
+ }
+
+ @Test
+ fun testLoadsMetadataOnBackground() {
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ verify(backgroundExecutor).execute(anyObject())
+ }
+
+ @Test
+ fun testOnMetaDataLoaded_callsListener() {
+ val listener = mock(MediaDataManager.Listener::class.java)
+ mediaDataManager.addListener(listener)
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java))
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(null), anyObject())
+ }
+
+ @Test
+ fun testHasAnyMedia_whenAddingMedia() {
+ assertThat(mediaDataManager.hasAnyMedia()).isFalse()
+ val data = mock(MediaData::class.java)
+
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = data)
+ assertThat(mediaDataManager.hasAnyMedia()).isTrue()
+ }
+
+ @Test
+ fun testOnNotificationRemoved_doesntHaveMedia() {
+ val data = mock(MediaData::class.java)
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = data)
+ mediaDataManager.onNotificationRemoved(KEY)
+ assertThat(mediaDataManager.hasAnyMedia()).isFalse()
+ }
+
+ @Test
+ fun testOnNotificationRemoved_callsListener() {
+ val listener = mock(MediaDataManager.Listener::class.java)
+ mediaDataManager.addListener(listener)
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java))
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ verify(listener).onMediaDataRemoved(eq(KEY))
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
index 0ae9461d38b1..61f5a7bdd3b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
@@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
@@ -40,6 +41,8 @@ import org.junit.runner.RunWith;
@SmallTest
public class AutoAddTrackerTest extends SysuiTestCase {
+ private static final int USER = 0;
+
private AutoAddTracker mAutoTracker;
@Before
@@ -51,7 +54,7 @@ public class AutoAddTrackerTest extends SysuiTestCase {
public void testMigration() {
Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true);
- mAutoTracker = new AutoAddTracker(mContext);
+ mAutoTracker = new AutoAddTracker(mContext, USER);
assertTrue(mAutoTracker.isAdded(SAVER));
assertTrue(mAutoTracker.isAdded(WORK));
@@ -68,7 +71,7 @@ public class AutoAddTrackerTest extends SysuiTestCase {
@Test
public void testChangeFromBackup() {
- mAutoTracker = new AutoAddTracker(mContext);
+ mAutoTracker = new AutoAddTracker(mContext, USER);
assertFalse(mAutoTracker.isAdded(SAVER));
@@ -82,7 +85,7 @@ public class AutoAddTrackerTest extends SysuiTestCase {
@Test
public void testSetAdded() {
- mAutoTracker = new AutoAddTracker(mContext);
+ mAutoTracker = new AutoAddTracker(mContext, USER);
assertFalse(mAutoTracker.isAdded(SAVER));
mAutoTracker.setTileAdded(SAVER);
@@ -94,16 +97,35 @@ public class AutoAddTrackerTest extends SysuiTestCase {
@Test
public void testPersist() {
- mAutoTracker = new AutoAddTracker(mContext);
+ mAutoTracker = new AutoAddTracker(mContext, USER);
assertFalse(mAutoTracker.isAdded(SAVER));
mAutoTracker.setTileAdded(SAVER);
mAutoTracker.destroy();
- mAutoTracker = new AutoAddTracker(mContext);
+ mAutoTracker = new AutoAddTracker(mContext, USER);
assertTrue(mAutoTracker.isAdded(SAVER));
mAutoTracker.destroy();
}
+
+ @Test
+ public void testIndependentUsers() {
+ mAutoTracker = new AutoAddTracker(mContext, USER);
+ mAutoTracker.setTileAdded(SAVER);
+
+ mAutoTracker = new AutoAddTracker(mContext, USER + 1);
+ assertFalse(mAutoTracker.isAdded(SAVER));
+ }
+
+ @Test
+ public void testChangeUser() {
+ mAutoTracker = new AutoAddTracker(mContext, USER);
+ mAutoTracker.setTileAdded(SAVER);
+
+ mAutoTracker = new AutoAddTracker(mContext, USER + 1);
+ mAutoTracker.changeUser(UserHandle.of(USER));
+ assertTrue(mAutoTracker.isAdded(SAVER));
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index e58a3a6bf5d7..ea5449b4448e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -96,6 +96,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
@Test
public void testUnmanaged() {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
+ when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(false);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
@@ -317,6 +318,33 @@ public class QSSecurityFooterTest extends SysuiTestCase {
}
@Test
+ public void testProfileOwnerOfOrganizationOwnedDeviceNoName() {
+ when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
+
+ mFooter.refreshState();
+ TestableLooper.get(this).processAllMessages();
+
+ assertEquals(mContext.getString(
+ R.string.quick_settings_disclosure_management),
+ mFooterText.getText());
+ }
+
+ @Test
+ public void testProfileOwnerOfOrganizationOwnedDeviceWithName() {
+ when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
+ when(mSecurityController.getWorkProfileOrganizationName())
+ .thenReturn(MANAGING_ORGANIZATION);
+
+ mFooter.refreshState();
+ TestableLooper.get(this).processAllMessages();
+
+ assertEquals(mContext.getString(
+ R.string.quick_settings_disclosure_named_management,
+ MANAGING_ORGANIZATION),
+ mFooterText.getText());
+ }
+
+ @Test
public void testVpnEnabled() {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
index 407e1e671f86..314b19140e7a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -51,7 +52,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -60,7 +60,7 @@ import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class ForegroundCoordinatorTest extends SysuiTestCase {
+public class AppOpsCoordinatorTest extends SysuiTestCase {
private static final String TEST_PKG = "test_pkg";
private static final int NOTIF_USER_ID = 0;
@@ -68,12 +68,11 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
@Mock private AppOpsController mAppOpsController;
@Mock private NotifPipeline mNotifPipeline;
- @Captor private ArgumentCaptor<AppOpsController.Callback> mAppOpsCaptor;
-
private NotificationEntry mEntry;
private Notification mNotification;
- private ForegroundCoordinator mForegroundCoordinator;
+ private AppOpsCoordinator mAppOpsCoordinator;
private NotifFilter mForegroundFilter;
+ private NotifCollectionListener mNotifCollectionListener;
private AppOpsController.Callback mAppOpsCallback;
private NotifLifetimeExtender mForegroundNotifLifetimeExtender;
@@ -85,8 +84,8 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
allowTestableLooperAsMainThread();
- mForegroundCoordinator =
- new ForegroundCoordinator(
+ mAppOpsCoordinator =
+ new AppOpsCoordinator(
mForegroundServiceController,
mAppOpsController,
mExecutor);
@@ -97,19 +96,32 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
.setNotification(mNotification)
.build();
+ mAppOpsCoordinator.attach(mNotifPipeline);
+
+ // capture filter
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
+ verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
+ mForegroundFilter = filterCaptor.getValue();
+
+ // capture lifetime extender
ArgumentCaptor<NotifLifetimeExtender> lifetimeExtenderCaptor =
ArgumentCaptor.forClass(NotifLifetimeExtender.class);
-
- mForegroundCoordinator.attach(mNotifPipeline);
- verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
verify(mNotifPipeline, times(1)).addNotificationLifetimeExtender(
lifetimeExtenderCaptor.capture());
- verify(mAppOpsController).addCallback(any(int[].class), mAppOpsCaptor.capture());
-
- mForegroundFilter = filterCaptor.getValue();
mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue();
- mAppOpsCallback = mAppOpsCaptor.getValue();
+
+ // capture notifCollectionListener
+ ArgumentCaptor<NotifCollectionListener> notifCollectionCaptor =
+ ArgumentCaptor.forClass(NotifCollectionListener.class);
+ verify(mNotifPipeline, times(1)).addCollectionListener(
+ notifCollectionCaptor.capture());
+ mNotifCollectionListener = notifCollectionCaptor.getValue();
+
+ // capture app ops callback
+ ArgumentCaptor<AppOpsController.Callback> appOpsCaptor =
+ ArgumentCaptor.forClass(AppOpsController.Callback.class);
+ verify(mAppOpsController).addCallback(any(int[].class), appOpsCaptor.capture());
+ mAppOpsCallback = appOpsCaptor.getValue();
}
@Test
@@ -199,15 +211,14 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
.setNotification(mNotification)
.build();
- // THEN don't extend the lifetime because the extended time exceeds
- // ForegroundCoordinator.MIN_FGS_TIME_MS
+ // THEN don't extend the lifetime because the extended time exceeds MIN_FGS_TIME_MS
assertFalse(mForegroundNotifLifetimeExtender
.shouldExtendLifetime(mEntry, NotificationListenerService.REASON_CLICK));
}
@Test
- public void testAppOpsAreApplied() {
- // GIVEN Three current notifications, two with the same key but from different users
+ public void testAppOpsUpdateOnlyAppliedToRelevantNotificationWithStandardLayout() {
+ // GIVEN three current notifications, two with the same key but from different users
NotificationEntry entry1 = new NotificationEntryBuilder()
.setUser(new UserHandle(NOTIF_USER_ID))
.setPkg(TEST_PKG)
@@ -218,16 +229,16 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
.setPkg(TEST_PKG)
.setId(2)
.build();
- NotificationEntry entry2Other = new NotificationEntryBuilder()
+ NotificationEntry entry3_diffUser = new NotificationEntryBuilder()
.setUser(new UserHandle(NOTIF_USER_ID + 1))
.setPkg(TEST_PKG)
.setId(2)
.build();
- when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry2Other));
+ when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3_diffUser));
- // GIVEN that entry2 is currently associated with a foreground service
- when(mForegroundServiceController.getStandardLayoutKey(0, TEST_PKG))
- .thenReturn(entry2.getKey());
+ // GIVEN that only entry2 has a standard layout
+ when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG))
+ .thenReturn(new ArraySet<>(List.of(entry2.getKey())));
// WHEN a new app ops code comes in
mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
@@ -242,7 +253,46 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
entry2.mActiveAppOps);
assertEquals(
new ArraySet<>(),
- entry2Other.mActiveAppOps);
+ entry3_diffUser.mActiveAppOps);
+ }
+
+ @Test
+ public void testAppOpsUpdateAppliedToAllNotificationsWithStandardLayouts() {
+ // GIVEN three notifications with standard layouts
+ NotificationEntry entry1 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(1)
+ .build();
+ NotificationEntry entry2 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(2)
+ .build();
+ NotificationEntry entry3 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(3)
+ .build();
+ when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3));
+ when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG))
+ .thenReturn(new ArraySet<>(List.of(entry1.getKey(), entry2.getKey(),
+ entry3.getKey())));
+
+ // WHEN a new app ops code comes in
+ mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
+ mExecutor.runAllReady();
+
+ // THEN all entries get updated
+ assertEquals(
+ new ArraySet<>(List.of(47)),
+ entry1.mActiveAppOps);
+ assertEquals(
+ new ArraySet<>(List.of(47)),
+ entry2.mActiveAppOps);
+ assertEquals(
+ new ArraySet<>(List.of(47)),
+ entry3.mActiveAppOps);
}
@Test
@@ -254,8 +304,8 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
.setId(2)
.build();
when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry));
- when(mForegroundServiceController.getStandardLayoutKey(0, TEST_PKG))
- .thenReturn(entry.getKey());
+ when(mForegroundServiceController.getStandardLayoutKeys(0, TEST_PKG))
+ .thenReturn(new ArraySet<>(List.of(entry.getKey())));
// GIVEN that the notification's app ops are already [47, 33]
mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
@@ -274,4 +324,25 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
new ArraySet<>(List.of(33)),
entry.mActiveAppOps);
}
+
+ @Test
+ public void testNullAppOps() {
+ // GIVEN one notification with app ops
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(2)
+ .build();
+ entry.mActiveAppOps.clear();
+ entry.mActiveAppOps.addAll(List.of(47, 33));
+
+ // WHEN the notification is updated and the foreground service controller returns null for
+ // this notification
+ when(mForegroundServiceController.getAppOps(entry.getSbn().getUser().getIdentifier(),
+ entry.getSbn().getPackageName())).thenReturn(null);
+ mNotifCollectionListener.onEntryUpdated(entry);
+
+ // THEN the entry's active app ops is updated to empty
+ assertTrue(entry.mActiveAppOps.isEmpty());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
index 87fc02062ad4..d21053bcd691 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
@@ -51,6 +51,7 @@ public class HideNotifsForOtherUsersCoordinatorTest extends SysuiTestCase {
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotifPipeline mNotifPipeline;
@Mock private PluggableListener<NotifFilter> mInvalidationListener;
+ @Mock private SharedCoordinatorLogger mLogger;
@Captor private ArgumentCaptor<UserChangedListener> mUserChangedListenerCaptor;
@Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor;
@@ -65,7 +66,7 @@ public class HideNotifsForOtherUsersCoordinatorTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
HideNotifsForOtherUsersCoordinator coordinator =
- new HideNotifsForOtherUsersCoordinator(mLockscreenUserManager);
+ new HideNotifsForOtherUsersCoordinator(mLockscreenUserManager, mLogger);
coordinator.attach(mNotifPipeline);
verify(mLockscreenUserManager).addUserChangedListener(mUserChangedListenerCaptor.capture());
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 05cdd802167a..0a959d11d7db 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
@@ -16,18 +16,34 @@
package com.android.systemui.statusbar.phone;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.isNotNull;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.ContextWrapper;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
+import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableContentResolver;
+import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -38,14 +54,18 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.statusbar.phone.AutoTileManagerTest.MyContextWrapper;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
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.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -64,9 +84,18 @@ public class AutoTileManagerTest extends SysuiTestCase {
private static final String TEST_CUSTOM_SPEC = "custom(" + TEST_COMPONENT + ")";
private static final String SEPARATOR = AutoTileManager.SETTING_SEPARATOR;
+ private static final int USER = 0;
+
@Mock private QSTileHost mQsTileHost;
@Mock private AutoAddTracker mAutoAddTracker;
@Mock private CastController mCastController;
+ @Mock private HotspotController mHotspotController;
+ @Mock private DataSaverController mDataSaverController;
+ @Mock private ManagedProfileController mManagedProfileController;
+ @Mock private NightDisplayListener mNightDisplayListener;
+ @Mock(answer = Answers.RETURNS_SELF)
+ private AutoAddTracker.Builder mAutoAddTrackerBuilder;
+ @Mock private Context mUserContext;
private AutoTileManager mAutoTileManager;
@@ -82,20 +111,114 @@ public class AutoTileManagerTest extends SysuiTestCase {
}
);
- mAutoTileManager = createAutoTileManager();
+ when(mAutoAddTrackerBuilder.build()).thenReturn(mAutoAddTracker);
+ when(mQsTileHost.getUserContext()).thenReturn(mUserContext);
+ when(mUserContext.getUser()).thenReturn(UserHandle.of(USER));
+
+ mAutoTileManager = createAutoTileManager(new
+ MyContextWrapper(mContext));
+ }
+
+ @After
+ public void tearDown() {
+ mAutoTileManager.destroy();
}
- private AutoTileManager createAutoTileManager() {
- return new AutoTileManager(mContext, mAutoAddTracker, mQsTileHost,
+ private AutoTileManager createAutoTileManager(Context context) {
+ return new AutoTileManager(context, mAutoAddTrackerBuilder, mQsTileHost,
Handler.createAsync(TestableLooper.get(this).getLooper()),
- mock(HotspotController.class),
- mock(DataSaverController.class),
- mock(ManagedProfileController.class),
- mock(NightDisplayListener.class),
+ mHotspotController,
+ mDataSaverController,
+ mManagedProfileController,
+ mNightDisplayListener,
mCastController);
}
@Test
+ public void testChangeUserCallbacksStoppedAndStarted() throws Exception {
+ TestableLooper.get(this).runWithLooper(() ->
+ mAutoTileManager.changeUser(UserHandle.of(USER + 1))
+ );
+
+ InOrder inOrderHotspot = inOrder(mHotspotController);
+ inOrderHotspot.verify(mHotspotController).removeCallback(any());
+ inOrderHotspot.verify(mHotspotController).addCallback(any());
+
+ InOrder inOrderDataSaver = inOrder(mDataSaverController);
+ inOrderDataSaver.verify(mDataSaverController).removeCallback(any());
+ inOrderDataSaver.verify(mDataSaverController).addCallback(any());
+
+ InOrder inOrderManagedProfile = inOrder(mManagedProfileController);
+ inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any());
+ inOrderManagedProfile.verify(mManagedProfileController).addCallback(any());
+
+ if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
+ InOrder inOrderNightDisplay = inOrder(mNightDisplayListener);
+ inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull());
+ inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull());
+ }
+
+ InOrder inOrderCast = inOrder(mCastController);
+ inOrderCast.verify(mCastController).removeCallback(any());
+ inOrderCast.verify(mCastController).addCallback(any());
+
+ SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
+ assertEquals(USER + 1, setting.getCurrentUser());
+ assertTrue(setting.isListening());
+ }
+
+ @Test
+ public void testChangeUserSomeCallbacksNotAdded() throws Exception {
+ when(mAutoAddTracker.isAdded("hotspot")).thenReturn(true);
+ when(mAutoAddTracker.isAdded("work")).thenReturn(true);
+ when(mAutoAddTracker.isAdded("cast")).thenReturn(true);
+ when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true);
+
+ TestableLooper.get(this).runWithLooper(() ->
+ mAutoTileManager.changeUser(UserHandle.of(USER + 1))
+ );
+
+ verify(mAutoAddTracker).changeUser(UserHandle.of(USER + 1));
+
+ InOrder inOrderHotspot = inOrder(mHotspotController);
+ inOrderHotspot.verify(mHotspotController).removeCallback(any());
+ inOrderHotspot.verify(mHotspotController, never()).addCallback(any());
+
+ InOrder inOrderDataSaver = inOrder(mDataSaverController);
+ inOrderDataSaver.verify(mDataSaverController).removeCallback(any());
+ inOrderDataSaver.verify(mDataSaverController).addCallback(any());
+
+ InOrder inOrderManagedProfile = inOrder(mManagedProfileController);
+ inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any());
+ inOrderManagedProfile.verify(mManagedProfileController, never()).addCallback(any());
+
+ if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
+ InOrder inOrderNightDisplay = inOrder(mNightDisplayListener);
+ inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull());
+ inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull());
+ }
+
+ InOrder inOrderCast = inOrder(mCastController);
+ inOrderCast.verify(mCastController).removeCallback(any());
+ inOrderCast.verify(mCastController, never()).addCallback(any());
+
+ SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
+ assertEquals(USER + 1, setting.getCurrentUser());
+ assertFalse(setting.isListening());
+ }
+
+ @Test
+ public void testGetCurrentUserId() throws Exception {
+ assertEquals(USER, mAutoTileManager.getCurrentUserId());
+
+ TestableLooper.get(this).runWithLooper(() ->
+ mAutoTileManager.changeUser(UserHandle.of(USER + 100))
+ );
+
+ assertEquals(USER + 100, mAutoTileManager.getCurrentUserId());
+ }
+
+ @Test
public void nightTileAdded_whenActivated() {
if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
return;
@@ -213,14 +336,14 @@ public class AutoTileManagerTest extends SysuiTestCase {
public void testEmptyArray_doesNotCrash() {
mContext.getOrCreateTestableResources().addOverride(
R.array.config_quickSettingsAutoAdd, new String[0]);
- createAutoTileManager();
+ createAutoTileManager(mContext).destroy();
}
@Test
public void testMissingConfig_doesNotCrash() {
mContext.getOrCreateTestableResources().addOverride(
R.array.config_quickSettingsAutoAdd, null);
- createAutoTileManager();
+ createAutoTileManager(mContext).destroy();
}
// Will only notify if it's listening
@@ -231,4 +354,22 @@ public class AutoTileManagerTest extends SysuiTestCase {
s.onChange(false);
}
}
+
+ class MyContextWrapper extends ContextWrapper {
+
+ private TestableContentResolver mSpiedTCR;
+
+ MyContextWrapper(TestableContext context) {
+ super(context);
+ mSpiedTCR = spy(context.getContentResolver());
+ doNothing().when(mSpiedTCR).registerContentObserver(any(), anyBoolean(), any(),
+ anyInt());
+ doNothing().when(mSpiedTCR).unregisterContentObserver(any());
+ }
+
+ @Override
+ public ContentResolver getContentResolver() {
+ return mSpiedTCR;
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
index fee5e32398c4..e8911a2f5d4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
@@ -41,6 +41,11 @@ public class FakeSecurityController extends BaseLeakChecker<SecurityControllerCa
}
@Override
+ public boolean isProfileOwnerOfOrganizationOwnedDevice() {
+ return false;
+ }
+
+ @Override
public String getDeviceOwnerName() {
return null;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index 8e34685cceec..2e874a6c2140 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -21,6 +21,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
+
import java.util.List;
public class FakeStatusBarIconController extends BaseLeakChecker<IconManager>
@@ -75,4 +76,8 @@ public class FakeStatusBarIconController extends BaseLeakChecker<IconManager>
public void removeAllIconsForSlot(String slot) {
}
+ @Override
+ public void setIconAccessibilityLiveRegion(String slot, int mode) {
+ }
+
}
diff --git a/packages/Tethering/OWNERS b/packages/Tethering/OWNERS
new file mode 100644
index 000000000000..5b42d490411e
--- /dev/null
+++ b/packages/Tethering/OWNERS
@@ -0,0 +1,2 @@
+include platform/packages/modules/NetworkStack/:/OWNERS
+markchien@google.com
diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt
index e90a2ccaa2a3..2d3108a0bff1 100644
--- a/packages/Tethering/jarjar-rules.txt
+++ b/packages/Tethering/jarjar-rules.txt
@@ -1,17 +1,11 @@
# These must be kept in sync with the framework-tethering-shared-srcs filegroup.
-# If there are files in that filegroup that do not appear here, the classes in the
+# Classes from the framework-tethering-shared-srcs filegroup.
+# If there are files in that filegroup that are not covered below, the classes in the
# module will be overwritten by the ones in the framework.
-# Don't jar-jar the entire package because tethering still use some internal classes
-# (like TrafficStatsConstants in com.android.internal.util)
-# TODO: simply these when tethering is built as system_current.
-rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
-rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
-rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
-rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
-rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
-rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
-rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1
-
+rule com.android.internal.util.** com.android.networkstack.tethering.util.@1
rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
rule android.net.shared.Inet4AddressUtils* com.android.networkstack.tethering.shared.Inet4AddressUtils@1
+
+# Classes from net-utils-framework-common
+rule com.android.net.module.util.** com.android.networkstack.tethering.util.@1 \ No newline at end of file
diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
index 4710a30b2998..aaaec17bf922 100644
--- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
+++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
@@ -16,7 +16,7 @@
package android.net.dhcp;
-import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
+import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
import android.net.LinkAddress;
import android.util.ArraySet;
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 1671dda4bd57..35c156304c77 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -19,13 +19,14 @@ package android.net.ip;
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
-import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.net.util.NetworkConstants.asByte;
import static android.net.util.PrefixUtils.asIpPrefix;
import static android.net.util.TetheringMessageBase.BASE_IPSERVER;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
+
import android.net.INetd;
import android.net.INetworkStackStatusCallback;
import android.net.IpPrefix;
@@ -615,8 +616,9 @@ public class IpServer extends StateMachine {
final Boolean setIfaceUp;
if (mInterfaceType == TetheringManager.TETHERING_WIFI
- || mInterfaceType == TetheringManager.TETHERING_WIFI_P2P) {
- // The WiFi stack has ownership of the interface up/down state.
+ || mInterfaceType == TetheringManager.TETHERING_WIFI_P2P
+ || mInterfaceType == TetheringManager.TETHERING_ETHERNET) {
+ // The WiFi and Ethernet stack has ownership of the interface up/down state.
// It is unclear whether the Bluetooth or USB stacks will manage their own
// state.
setIfaceUp = null;
@@ -1321,6 +1323,7 @@ public class IpServer extends StateMachine {
class UnavailableState extends State {
@Override
public void enter() {
+ mIpNeighborMonitor.stop();
mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
sendInterfaceState(STATE_UNAVAILABLE);
}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index fc27b6add052..20f30ea7a460 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -25,6 +25,8 @@ import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStats.UID_TETHERING;
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
+import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
+
import android.app.usage.NetworkStatsManager;
import android.net.INetd;
import android.net.MacAddress;
@@ -36,6 +38,7 @@ import android.net.ip.IpServer;
import android.net.netstats.provider.NetworkStatsProvider;
import android.net.util.SharedLog;
import android.net.util.TetheringUtils.ForwardedStats;
+import android.os.ConditionVariable;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
@@ -47,11 +50,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Objects;
/**
@@ -65,8 +70,7 @@ import java.util.Objects;
*/
public class BpfCoordinator {
private static final String TAG = BpfCoordinator.class.getSimpleName();
- @VisibleForTesting
- static final int DEFAULT_PERFORM_POLL_INTERVAL_MS = 5000; // TODO: Make it customizable.
+ private static final int DUMP_TIMEOUT_MS = 10_000;
@VisibleForTesting
enum StatsType {
@@ -85,6 +89,13 @@ public class BpfCoordinator {
@Nullable
private final BpfTetherStatsProvider mStatsProvider;
+ // True if BPF offload is supported, false otherwise. The BPF offload could be disabled by
+ // a runtime resource overlay package or device configuration. This flag is only initialized
+ // in the constructor because it is hard to unwind all existing change once device
+ // configuration is changed. Especially the forwarding rules. Keep the same setting
+ // to make it simpler. See also TetheringConfiguration.
+ private final boolean mIsBpfEnabled;
+
// Tracks whether BPF tethering is started or not. This is set by tethering before it
// starts the first IpServer and is cleared by tethering shortly before the last IpServer
// is stopped. Note that rule updates (especially deletions, but sometimes additions as
@@ -142,22 +153,34 @@ public class BpfCoordinator {
};
@VisibleForTesting
- public static class Dependencies {
- int getPerformPollInterval() {
- // TODO: Consider make this configurable.
- return DEFAULT_PERFORM_POLL_INTERVAL_MS;
- }
+ public abstract static class Dependencies {
+ /** Get handler. */
+ @NonNull public abstract Handler getHandler();
+
+ /** Get netd. */
+ @NonNull public abstract INetd getNetd();
+
+ /** Get network stats manager. */
+ @NonNull public abstract NetworkStatsManager getNetworkStatsManager();
+
+ /** Get shared log. */
+ @NonNull public abstract SharedLog getSharedLog();
+
+ /** Get tethering configuration. */
+ @Nullable public abstract TetheringConfiguration getTetherConfig();
}
@VisibleForTesting
- public BpfCoordinator(@NonNull Handler handler, @NonNull INetd netd,
- @NonNull NetworkStatsManager nsm, @NonNull SharedLog log, @NonNull Dependencies deps) {
- mHandler = handler;
- mNetd = netd;
- mLog = log.forSubComponent(TAG);
+ public BpfCoordinator(@NonNull Dependencies deps) {
+ mDeps = deps;
+ mHandler = mDeps.getHandler();
+ mNetd = mDeps.getNetd();
+ mLog = mDeps.getSharedLog().forSubComponent(TAG);
+ mIsBpfEnabled = isBpfEnabled();
BpfTetherStatsProvider provider = new BpfTetherStatsProvider();
try {
- nsm.registerNetworkStatsProvider(getClass().getSimpleName(), provider);
+ mDeps.getNetworkStatsManager().registerNetworkStatsProvider(
+ getClass().getSimpleName(), provider);
} catch (RuntimeException e) {
// TODO: Perhaps not allow to use BPF offload because the reregistration failure
// implied that no data limit could be applies on a metered upstream if any.
@@ -165,7 +188,6 @@ public class BpfCoordinator {
provider = null;
}
mStatsProvider = provider;
- mDeps = deps;
}
/**
@@ -177,6 +199,11 @@ public class BpfCoordinator {
public void startPolling() {
if (mPollingStarted) return;
+ if (!mIsBpfEnabled) {
+ mLog.i("Offload disabled");
+ return;
+ }
+
mPollingStarted = true;
maybeSchedulePollingStats();
@@ -211,6 +238,8 @@ public class BpfCoordinator {
*/
public void tetherOffloadRuleAdd(
@NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) {
+ if (!mIsBpfEnabled) return;
+
try {
// TODO: Perhaps avoid to add a duplicate rule.
mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel());
@@ -250,6 +279,8 @@ public class BpfCoordinator {
*/
public void tetherOffloadRuleRemove(
@NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) {
+ if (!mIsBpfEnabled) return;
+
try {
// TODO: Perhaps avoid to remove a non-existent rule.
mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel());
@@ -293,6 +324,8 @@ public class BpfCoordinator {
* Note that this can be only called on handler thread.
*/
public void tetherOffloadRuleClear(@NonNull final IpServer ipServer) {
+ if (!mIsBpfEnabled) return;
+
final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(
ipServer);
if (rules == null) return;
@@ -308,6 +341,8 @@ public class BpfCoordinator {
* Note that this can be only called on handler thread.
*/
public void tetherOffloadRuleUpdate(@NonNull final IpServer ipServer, int newUpstreamIfindex) {
+ if (!mIsBpfEnabled) return;
+
final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(
ipServer);
if (rules == null) return;
@@ -330,6 +365,8 @@ public class BpfCoordinator {
* Note that this can be only called on handler thread.
*/
public void addUpstreamNameToLookupTable(int upstreamIfindex, @NonNull String upstreamIface) {
+ if (!mIsBpfEnabled) return;
+
if (upstreamIfindex == 0 || TextUtils.isEmpty(upstreamIface)) return;
// The same interface index to name mapping may be added by different IpServer objects or
@@ -344,6 +381,77 @@ public class BpfCoordinator {
}
}
+ /**
+ * Dump information.
+ * Block the function until all the data are dumped on the handler thread or timed-out. The
+ * reason is that dumpsys invokes this function on the thread of caller and the data may only
+ * be allowed to be accessed on the handler thread.
+ */
+ public void dump(@NonNull IndentingPrintWriter pw) {
+ final ConditionVariable dumpDone = new ConditionVariable();
+ mHandler.post(() -> {
+ pw.println("mIsBpfEnabled: " + mIsBpfEnabled);
+ pw.println("Polling " + (mPollingStarted ? "started" : "not started"));
+ pw.println("Stats provider " + (mStatsProvider != null
+ ? "registered" : "not registered"));
+ pw.println("Upstream quota: " + mInterfaceQuotas.toString());
+ pw.println("Polling interval: " + getPollingInterval() + " ms");
+
+ pw.println("Forwarding stats:");
+ pw.increaseIndent();
+ if (mStats.size() == 0) {
+ pw.println("<empty>");
+ } else {
+ dumpStats(pw);
+ }
+ pw.decreaseIndent();
+
+ pw.println("Forwarding rules:");
+ pw.increaseIndent();
+ if (mIpv6ForwardingRules.size() == 0) {
+ pw.println("<empty>");
+ } else {
+ dumpIpv6ForwardingRules(pw);
+ }
+ pw.decreaseIndent();
+
+ dumpDone.open();
+ });
+ if (!dumpDone.block(DUMP_TIMEOUT_MS)) {
+ pw.println("... dump timed-out after " + DUMP_TIMEOUT_MS + "ms");
+ }
+ }
+
+ private void dumpStats(@NonNull IndentingPrintWriter pw) {
+ for (int i = 0; i < mStats.size(); i++) {
+ final int upstreamIfindex = mStats.keyAt(i);
+ final ForwardedStats stats = mStats.get(upstreamIfindex);
+ pw.println(String.format("%d(%s) - %s", upstreamIfindex, mInterfaceNames.get(
+ upstreamIfindex), stats.toString()));
+ }
+ }
+
+ private void dumpIpv6ForwardingRules(@NonNull IndentingPrintWriter pw) {
+ for (Map.Entry<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>> entry :
+ mIpv6ForwardingRules.entrySet()) {
+ IpServer ipServer = entry.getKey();
+ // The rule downstream interface index is paired with the interface name from
+ // IpServer#interfaceName. See #startIPv6, #updateIpv6ForwardingRules in IpServer.
+ final String downstreamIface = ipServer.interfaceName();
+ pw.println("[" + downstreamIface + "]: iif(iface) oif(iface) v6addr srcmac dstmac");
+
+ pw.increaseIndent();
+ LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = entry.getValue();
+ for (Ipv6ForwardingRule rule : rules.values()) {
+ final int upstreamIfindex = rule.upstreamIfindex;
+ pw.println(String.format("%d(%s) %d(%s) %s %s %s", upstreamIfindex,
+ mInterfaceNames.get(upstreamIfindex), rule.downstreamIfindex,
+ downstreamIface, rule.address, rule.srcMac, rule.dstMac));
+ }
+ pw.decreaseIndent();
+ }
+ }
+
/** IPv6 forwarding rule class. */
public static class Ipv6ForwardingRule {
public final int upstreamIfindex;
@@ -474,6 +582,11 @@ public class BpfCoordinator {
}
}
+ private boolean isBpfEnabled() {
+ final TetheringConfiguration config = mDeps.getTetherConfig();
+ return (config != null) ? config.isBpfOffloadEnabled() : true /* default value */;
+ }
+
private int getInterfaceIndexFromRules(@NonNull String ifName) {
for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules
.values()) {
@@ -625,6 +738,17 @@ public class BpfCoordinator {
updateQuotaAndStatsFromSnapshot(tetherStatsList);
}
+ @VisibleForTesting
+ int getPollingInterval() {
+ // The valid range of interval is DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS..max_long.
+ // Ignore the config value is less than the minimum polling interval. Note that the
+ // minimum interval definition is invoked as OffloadController#isPollingStatsNeeded does.
+ // TODO: Perhaps define a minimum polling interval constant.
+ final TetheringConfiguration config = mDeps.getTetherConfig();
+ final int configInterval = (config != null) ? config.getOffloadPollInterval() : 0;
+ return Math.max(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, configInterval);
+ }
+
private void maybeSchedulePollingStats() {
if (!mPollingStarted) return;
@@ -632,6 +756,23 @@ public class BpfCoordinator {
mHandler.removeCallbacks(mScheduledPollingTask);
}
- mHandler.postDelayed(mScheduledPollingTask, mDeps.getPerformPollInterval());
+ mHandler.postDelayed(mScheduledPollingTask, getPollingInterval());
+ }
+
+ // Return forwarding rule map. This is used for testing only.
+ // Note that this can be only called on handler thread.
+ @NonNull
+ @VisibleForTesting
+ final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
+ getForwardingRulesForTesting() {
+ return mIpv6ForwardingRules;
+ }
+
+ // Return upstream interface name map. This is used for testing only.
+ // Note that this can be only called on handler thread.
+ @NonNull
+ @VisibleForTesting
+ final SparseArray<String> getInterfaceNamesForTesting() {
+ return mInterfaceNames;
}
}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 2f01186b117d..c72ac52740d7 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -63,6 +63,7 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
+import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -286,8 +287,6 @@ public class Tethering {
mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
mForwardedDownstreams = new LinkedHashSet<>();
- mBpfCoordinator = mDeps.getBpfCoordinator(
- mHandler, mNetd, mLog, new BpfCoordinator.Dependencies());
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
@@ -325,6 +324,36 @@ public class Tethering {
// Load tethering configuration.
updateConfiguration();
+ // Must be initialized after tethering configuration is loaded because BpfCoordinator
+ // constructor needs to use the configuration.
+ mBpfCoordinator = mDeps.getBpfCoordinator(
+ new BpfCoordinator.Dependencies() {
+ @NonNull
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ @NonNull
+ public INetd getNetd() {
+ return mNetd;
+ }
+
+ @NonNull
+ public NetworkStatsManager getNetworkStatsManager() {
+ return mContext.getSystemService(NetworkStatsManager.class);
+ }
+
+ @NonNull
+ public SharedLog getSharedLog() {
+ return mLog;
+ }
+
+ @Nullable
+ public TetheringConfiguration getTetherConfig() {
+ return mConfig;
+ }
+ });
+
startStateMachineUpdaters();
}
@@ -2236,6 +2265,11 @@ public class Tethering {
mOffloadController.dump(pw);
pw.decreaseIndent();
+ pw.println("BPF offload:");
+ pw.increaseIndent();
+ mBpfCoordinator.dump(pw);
+ pw.decreaseIndent();
+
pw.println("Private address coordinator:");
pw.increaseIndent();
mPrivateAddressCoordinator.dump(pw);
@@ -2370,7 +2404,7 @@ public class Tethering {
final TetherState tetherState = new TetherState(
new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator,
makeControlCallback(), mConfig.enableLegacyDhcpServer,
- mConfig.enableBpfOffload, mPrivateAddressCoordinator,
+ mConfig.isBpfOffloadEnabled(), mPrivateAddressCoordinator,
mDeps.getIpServerDependencies()));
mTetherStates.put(iface, tetherState);
tetherState.ipServer.start();
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 1d45f129b51b..18b2b7804fb0 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -101,8 +101,6 @@ public class TetheringConfiguration {
public final String[] legacyDhcpRanges;
public final String[] defaultIPv4DNS;
public final boolean enableLegacyDhcpServer;
- // TODO: Add to TetheringConfigurationParcel if required.
- public final boolean enableBpfOffload;
public final String[] provisioningApp;
public final String provisioningAppNoUi;
@@ -112,6 +110,8 @@ public class TetheringConfiguration {
public final int activeDataSubId;
private final int mOffloadPollInterval;
+ // TODO: Add to TetheringConfigurationParcel if required.
+ private final boolean mEnableBpfOffload;
public TetheringConfiguration(Context ctx, SharedLog log, int id) {
final SharedLog configLog = log.forSubComponent("config");
@@ -138,7 +138,7 @@ public class TetheringConfiguration {
legacyDhcpRanges = getLegacyDhcpRanges(res);
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
- enableBpfOffload = getEnableBpfOffload(res);
+ mEnableBpfOffload = getEnableBpfOffload(res);
enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);
provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
@@ -222,7 +222,7 @@ public class TetheringConfiguration {
pw.println(provisioningAppNoUi);
pw.print("enableBpfOffload: ");
- pw.println(enableBpfOffload);
+ pw.println(mEnableBpfOffload);
pw.print("enableLegacyDhcpServer: ");
pw.println(enableLegacyDhcpServer);
@@ -244,7 +244,7 @@ public class TetheringConfiguration {
toIntArray(preferredUpstreamIfaceTypes)));
sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
- sj.add(String.format("enableBpfOffload:%s", enableBpfOffload));
+ sj.add(String.format("enableBpfOffload:%s", mEnableBpfOffload));
sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
return String.format("TetheringConfiguration{%s}", sj.toString());
}
@@ -283,6 +283,10 @@ public class TetheringConfiguration {
return mOffloadPollInterval;
}
+ public boolean isBpfOffloadEnabled() {
+ return mEnableBpfOffload;
+ }
+
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 31f747d3c4b5..131a5fbf2abe 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -46,11 +46,8 @@ public abstract class TetheringDependencies {
* Get a reference to the BpfCoordinator to be used by tethering.
*/
public @NonNull BpfCoordinator getBpfCoordinator(
- @NonNull Handler handler, @NonNull INetd netd, @NonNull SharedLog log,
@NonNull BpfCoordinator.Dependencies deps) {
- final NetworkStatsManager statsManager =
- (NetworkStatsManager) getContext().getSystemService(Context.NETWORK_STATS_SERVICE);
- return new BpfCoordinator(handler, netd, statsManager, log, deps);
+ return new BpfCoordinator(deps);
}
/**
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index c3bc915a232d..30a9d2252ea6 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -36,7 +36,8 @@ import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH;
import static android.net.netlink.StructNdMsg.NUD_FAILED;
import static android.net.netlink.StructNdMsg.NUD_REACHABLE;
import static android.net.netlink.StructNdMsg.NUD_STALE;
-import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
+
+import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -89,12 +90,14 @@ import android.os.test.TestLooper;
import android.text.TextUtils;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.networkstack.tethering.BpfCoordinator;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
import com.android.networkstack.tethering.PrivateAddressCoordinator;
+import com.android.networkstack.tethering.TetheringConfiguration;
import org.junit.Before;
import org.junit.Test;
@@ -142,6 +145,7 @@ public class IpServerTest {
@Mock private IpServer.Dependencies mDependencies;
@Mock private PrivateAddressCoordinator mAddressCoordinator;
@Mock private NetworkStatsManager mStatsManager;
+ @Mock private TetheringConfiguration mTetherConfig;
@Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor;
@@ -225,10 +229,35 @@ public class IpServerTest {
MockitoAnnotations.initMocks(this);
when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
when(mAddressCoordinator.requestDownstreamAddress(any())).thenReturn(mTestAddress);
-
- BpfCoordinator bc = new BpfCoordinator(new Handler(mLooper.getLooper()), mNetd,
- mStatsManager, mSharedLog, new BpfCoordinator.Dependencies());
- mBpfCoordinator = spy(bc);
+ when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */);
+
+ mBpfCoordinator = spy(new BpfCoordinator(
+ new BpfCoordinator.Dependencies() {
+ @NonNull
+ public Handler getHandler() {
+ return new Handler(mLooper.getLooper());
+ }
+
+ @NonNull
+ public INetd getNetd() {
+ return mNetd;
+ }
+
+ @NonNull
+ public NetworkStatsManager getNetworkStatsManager() {
+ return mStatsManager;
+ }
+
+ @NonNull
+ public SharedLog getSharedLog() {
+ return mSharedLog;
+ }
+
+ @Nullable
+ public TetheringConfiguration getTetherConfig() {
+ return mTetherConfig;
+ }
+ }));
}
@Test
@@ -671,18 +700,21 @@ public class IpServerTest {
}
}
- private TetherOffloadRuleParcel matches(
+ @NonNull
+ private static TetherOffloadRuleParcel matches(
int upstreamIfindex, InetAddress dst, MacAddress dstMac) {
return argThat(new TetherOffloadRuleParcelMatcher(upstreamIfindex, dst, dstMac));
}
+ @NonNull
private static Ipv6ForwardingRule makeForwardingRule(
int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac) {
return new Ipv6ForwardingRule(upstreamIfindex, TEST_IFACE_PARAMS.index,
(Inet6Address) dst, TEST_IFACE_PARAMS.macAddr, dstMac);
}
- private TetherStatsParcel buildEmptyTetherStatsParcel(int ifIndex) {
+ @NonNull
+ private static TetherStatsParcel buildEmptyTetherStatsParcel(int ifIndex) {
TetherStatsParcel parcel = new TetherStatsParcel();
parcel.ifIndex = ifIndex;
return parcel;
@@ -828,6 +860,7 @@ public class IpServerTest {
verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
+ verify(mIpNeighborMonitor).stop();
resetNetdAndBpfCoordinator();
}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index e2d7aab4e33f..64242ae8255f 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -25,48 +25,76 @@ import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStats.UID_TETHERING;
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
-import static com.android.networkstack.tethering.BpfCoordinator
- .DEFAULT_PERFORM_POLL_INTERVAL_MS;
import static com.android.networkstack.tethering.BpfCoordinator.StatsType;
import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_IFACE;
import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_UID;
-
-import static junit.framework.Assert.assertNotNull;
-
+import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.annotation.NonNull;
import android.app.usage.NetworkStatsManager;
import android.net.INetd;
+import android.net.InetAddresses;
+import android.net.MacAddress;
import android.net.NetworkStats;
+import android.net.TetherOffloadRuleParcel;
import android.net.TetherStatsParcel;
+import android.net.ip.IpServer;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.test.TestLooper;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
import com.android.testutils.TestableNetworkStatsProviderCbBinder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.Inet6Address;
+import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class BpfCoordinatorTest {
+ private static final int DOWNSTREAM_IFINDEX = 10;
+ private static final MacAddress DOWNSTREAM_MAC = MacAddress.ALL_ZEROS_ADDRESS;
+ private static final InetAddress NEIGH_A = InetAddresses.parseNumericAddress("2001:db8::1");
+ private static final InetAddress NEIGH_B = InetAddresses.parseNumericAddress("2001:db8::2");
+ private static final MacAddress MAC_A = MacAddress.fromString("00:00:00:00:00:0a");
+ private static final MacAddress MAC_B = MacAddress.fromString("11:22:33:00:00:0b");
+
@Mock private NetworkStatsManager mStatsManager;
@Mock private INetd mNetd;
+ @Mock private IpServer mIpServer;
+ @Mock private TetheringConfiguration mTetherConfig;
+
// Late init since methods must be called by the thread that created this object.
private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb;
private BpfCoordinator.BpfTetherStatsProvider mTetherStatsProvider;
@@ -75,14 +103,35 @@ public class BpfCoordinatorTest {
private final TestLooper mTestLooper = new TestLooper();
private BpfCoordinator.Dependencies mDeps =
new BpfCoordinator.Dependencies() {
- @Override
- int getPerformPollInterval() {
- return DEFAULT_PERFORM_POLL_INTERVAL_MS;
+ @NonNull
+ public Handler getHandler() {
+ return new Handler(mTestLooper.getLooper());
+ }
+
+ @NonNull
+ public INetd getNetd() {
+ return mNetd;
+ }
+
+ @NonNull
+ public NetworkStatsManager getNetworkStatsManager() {
+ return mStatsManager;
+ }
+
+ @NonNull
+ public SharedLog getSharedLog() {
+ return new SharedLog("test");
+ }
+
+ @Nullable
+ public TetheringConfiguration getTetherConfig() {
+ return mTetherConfig;
}
};
@Before public void setUp() {
MockitoAnnotations.initMocks(this);
+ when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */);
}
private void waitForIdle() {
@@ -95,9 +144,7 @@ public class BpfCoordinatorTest {
@NonNull
private BpfCoordinator makeBpfCoordinator() throws Exception {
- BpfCoordinator coordinator = new BpfCoordinator(
- new Handler(mTestLooper.getLooper()), mNetd, mStatsManager, new SharedLog("test"),
- mDeps);
+ final BpfCoordinator coordinator = new BpfCoordinator(mDeps);
final ArgumentCaptor<BpfCoordinator.BpfTetherStatsProvider>
tetherStatsProviderCaptor =
ArgumentCaptor.forClass(BpfCoordinator.BpfTetherStatsProvider.class);
@@ -130,9 +177,11 @@ public class BpfCoordinatorTest {
return parcel;
}
+ // Set up specific tether stats list and wait for the stats cache is updated by polling thread
+ // in the coordinator. Beware of that it is only used for the default polling interval.
private void setTetherOffloadStatsList(TetherStatsParcel[] tetherStatsList) throws Exception {
when(mNetd.tetherOffloadGetStats()).thenReturn(tetherStatsList);
- mTestLooper.moveTimeForward(DEFAULT_PERFORM_POLL_INTERVAL_MS);
+ mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
waitForIdle();
}
@@ -201,7 +250,7 @@ public class BpfCoordinatorTest {
clearInvocations(mNetd);
// Verify the polling update thread stopped.
- mTestLooper.moveTimeForward(DEFAULT_PERFORM_POLL_INTERVAL_MS);
+ mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
waitForIdle();
verify(mNetd, never()).tetherOffloadGetStats();
}
@@ -226,21 +275,333 @@ public class BpfCoordinatorTest {
when(mNetd.tetherOffloadGetStats()).thenReturn(
new TetherStatsParcel[] {buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0)});
mTetherStatsProvider.onSetAlert(100);
- mTestLooper.moveTimeForward(DEFAULT_PERFORM_POLL_INTERVAL_MS);
+ mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
waitForIdle();
mTetherStatsProviderCb.assertNoCallback();
// Verify that notifyAlertReached fired when quota is reached.
when(mNetd.tetherOffloadGetStats()).thenReturn(
new TetherStatsParcel[] {buildTestTetherStatsParcel(mobileIfIndex, 50, 0, 50, 0)});
- mTestLooper.moveTimeForward(DEFAULT_PERFORM_POLL_INTERVAL_MS);
+ mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
waitForIdle();
mTetherStatsProviderCb.expectNotifyAlertReached();
// Verify that set quota with UNLIMITED won't trigger any callback.
mTetherStatsProvider.onSetAlert(QUOTA_UNLIMITED);
- mTestLooper.moveTimeForward(DEFAULT_PERFORM_POLL_INTERVAL_MS);
+ mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
waitForIdle();
mTetherStatsProviderCb.assertNoCallback();
}
+
+ // The custom ArgumentMatcher simply comes from IpServerTest.
+ // TODO: move both of them into a common utility class for reusing the code.
+ private static class TetherOffloadRuleParcelMatcher implements
+ ArgumentMatcher<TetherOffloadRuleParcel> {
+ public final int upstreamIfindex;
+ public final int downstreamIfindex;
+ public final Inet6Address address;
+ public final MacAddress srcMac;
+ public final MacAddress dstMac;
+
+ TetherOffloadRuleParcelMatcher(@NonNull Ipv6ForwardingRule rule) {
+ upstreamIfindex = rule.upstreamIfindex;
+ downstreamIfindex = rule.downstreamIfindex;
+ address = rule.address;
+ srcMac = rule.srcMac;
+ dstMac = rule.dstMac;
+ }
+
+ public boolean matches(@NonNull TetherOffloadRuleParcel parcel) {
+ return upstreamIfindex == parcel.inputInterfaceIndex
+ && (downstreamIfindex == parcel.outputInterfaceIndex)
+ && Arrays.equals(address.getAddress(), parcel.destination)
+ && (128 == parcel.prefixLength)
+ && Arrays.equals(srcMac.toByteArray(), parcel.srcL2Address)
+ && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address);
+ }
+
+ public String toString() {
+ return String.format("TetherOffloadRuleParcelMatcher(%d, %d, %s, %s, %s",
+ upstreamIfindex, downstreamIfindex, address.getHostAddress(), srcMac, dstMac);
+ }
+ }
+
+ @NonNull
+ private TetherOffloadRuleParcel matches(@NonNull Ipv6ForwardingRule rule) {
+ return argThat(new TetherOffloadRuleParcelMatcher(rule));
+ }
+
+ @NonNull
+ private static Ipv6ForwardingRule buildTestForwardingRule(
+ int upstreamIfindex, @NonNull InetAddress address, @NonNull MacAddress dstMac) {
+ return new Ipv6ForwardingRule(upstreamIfindex, DOWNSTREAM_IFINDEX, (Inet6Address) address,
+ DOWNSTREAM_MAC, dstMac);
+ }
+
+ @Test
+ public void testSetDataLimit() throws Exception {
+ setupFunctioningNetdInterface();
+
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+
+ final String mobileIface = "rmnet_data0";
+ final Integer mobileIfIndex = 100;
+ coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
+
+ // [1] Default limit.
+ // Set the unlimited quota as default if the service has never applied a data limit for a
+ // given upstream. Note that the data limit only be applied on an upstream which has rules.
+ final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
+ final InOrder inOrder = inOrder(mNetd);
+ coordinator.tetherOffloadRuleAdd(mIpServer, rule);
+ inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(rule));
+ inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, QUOTA_UNLIMITED);
+ inOrder.verifyNoMoreInteractions();
+
+ // [2] Specific limit.
+ // Applying the data limit boundary {min, 1gb, max, infinity} on current upstream.
+ for (final long quota : new long[] {0, 1048576000, Long.MAX_VALUE, QUOTA_UNLIMITED}) {
+ mTetherStatsProvider.onSetLimit(mobileIface, quota);
+ waitForIdle();
+ inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, quota);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ // [3] Invalid limit.
+ // The valid range of quota is 0..max_int64 or -1 (unlimited).
+ final long invalidLimit = Long.MIN_VALUE;
+ try {
+ mTetherStatsProvider.onSetLimit(mobileIface, invalidLimit);
+ waitForIdle();
+ fail("No exception thrown for invalid limit " + invalidLimit + ".");
+ } catch (IllegalArgumentException expected) {
+ assertEquals(expected.getMessage(), "invalid quota value " + invalidLimit);
+ }
+ }
+
+ // TODO: Test the case in which the rules are changed from different IpServer objects.
+ @Test
+ public void testSetDataLimitOnRuleChange() throws Exception {
+ setupFunctioningNetdInterface();
+
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+
+ final String mobileIface = "rmnet_data0";
+ final Integer mobileIfIndex = 100;
+ coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
+
+ // Applying a data limit to the current upstream does not take any immediate action.
+ // The data limit could be only set on an upstream which has rules.
+ final long limit = 12345;
+ final InOrder inOrder = inOrder(mNetd);
+ mTetherStatsProvider.onSetLimit(mobileIface, limit);
+ waitForIdle();
+ inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong());
+
+ // Adding the first rule on current upstream immediately sends the quota to netd.
+ final Ipv6ForwardingRule ruleA = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
+ coordinator.tetherOffloadRuleAdd(mIpServer, ruleA);
+ inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ruleA));
+ inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, limit);
+ inOrder.verifyNoMoreInteractions();
+
+ // Adding the second rule on current upstream does not send the quota to netd.
+ final Ipv6ForwardingRule ruleB = buildTestForwardingRule(mobileIfIndex, NEIGH_B, MAC_B);
+ coordinator.tetherOffloadRuleAdd(mIpServer, ruleB);
+ inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ruleB));
+ inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong());
+
+ // Removing the second rule on current upstream does not send the quota to netd.
+ coordinator.tetherOffloadRuleRemove(mIpServer, ruleB);
+ inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ruleB));
+ inOrder.verify(mNetd, never()).tetherOffloadSetInterfaceQuota(anyInt(), anyLong());
+
+ // Removing the last rule on current upstream immediately sends the cleanup stuff to netd.
+ when(mNetd.tetherOffloadGetAndClearStats(mobileIfIndex))
+ .thenReturn(buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0));
+ coordinator.tetherOffloadRuleRemove(mIpServer, ruleA);
+ inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ruleA));
+ inOrder.verify(mNetd).tetherOffloadGetAndClearStats(mobileIfIndex);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testTetherOffloadRuleUpdateAndClear() throws Exception {
+ setupFunctioningNetdInterface();
+
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+
+ final String ethIface = "eth1";
+ final String mobileIface = "rmnet_data0";
+ final Integer ethIfIndex = 100;
+ final Integer mobileIfIndex = 101;
+ coordinator.addUpstreamNameToLookupTable(ethIfIndex, ethIface);
+ coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
+
+ final InOrder inOrder = inOrder(mNetd);
+
+ // Before the rule test, here are the additional actions while the rules are changed.
+ // - After adding the first rule on a given upstream, the coordinator adds a data limit.
+ // If the service has never applied the data limit, set an unlimited quota as default.
+ // - After removing the last rule on a given upstream, the coordinator gets the last stats.
+ // Then, it clears the stats and the limit entry from BPF maps.
+ // See tetherOffloadRule{Add, Remove, Clear, Clean}.
+
+ // [1] Adding rules on the upstream Ethernet.
+ // Note that the default data limit is applied after the first rule is added.
+ final Ipv6ForwardingRule ethernetRuleA = buildTestForwardingRule(
+ ethIfIndex, NEIGH_A, MAC_A);
+ final Ipv6ForwardingRule ethernetRuleB = buildTestForwardingRule(
+ ethIfIndex, NEIGH_B, MAC_B);
+
+ coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleA);
+ inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ethernetRuleA));
+ inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(ethIfIndex, QUOTA_UNLIMITED);
+
+ coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleB);
+ inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(ethernetRuleB));
+
+ // [2] Update the existing rules from Ethernet to cellular.
+ final Ipv6ForwardingRule mobileRuleA = buildTestForwardingRule(
+ mobileIfIndex, NEIGH_A, MAC_A);
+ final Ipv6ForwardingRule mobileRuleB = buildTestForwardingRule(
+ mobileIfIndex, NEIGH_B, MAC_B);
+ when(mNetd.tetherOffloadGetAndClearStats(ethIfIndex))
+ .thenReturn(buildTestTetherStatsParcel(ethIfIndex, 10, 20, 30, 40));
+
+ // Update the existing rules for upstream changes. The rules are removed and re-added one
+ // by one for updating upstream interface index by #tetherOffloadRuleUpdate.
+ coordinator.tetherOffloadRuleUpdate(mIpServer, mobileIfIndex);
+ inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ethernetRuleA));
+ inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(mobileRuleA));
+ inOrder.verify(mNetd).tetherOffloadSetInterfaceQuota(mobileIfIndex, QUOTA_UNLIMITED);
+ inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(ethernetRuleB));
+ inOrder.verify(mNetd).tetherOffloadGetAndClearStats(ethIfIndex);
+ inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(mobileRuleB));
+
+ // [3] Clear all rules for a given IpServer.
+ when(mNetd.tetherOffloadGetAndClearStats(mobileIfIndex))
+ .thenReturn(buildTestTetherStatsParcel(mobileIfIndex, 50, 60, 70, 80));
+ coordinator.tetherOffloadRuleClear(mIpServer);
+ inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(mobileRuleA));
+ inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(mobileRuleB));
+ inOrder.verify(mNetd).tetherOffloadGetAndClearStats(mobileIfIndex);
+
+ // [4] Force pushing stats update to verify that the last diff of stats is reported on all
+ // upstreams.
+ mTetherStatsProvider.pushTetherStats();
+ mTetherStatsProviderCb.expectNotifyStatsUpdated(
+ new NetworkStats(0L, 2)
+ .addEntry(buildTestEntry(STATS_PER_IFACE, ethIface, 10, 20, 30, 40))
+ .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 50, 60, 70, 80)),
+ new NetworkStats(0L, 2)
+ .addEntry(buildTestEntry(STATS_PER_UID, ethIface, 10, 20, 30, 40))
+ .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 50, 60, 70, 80)));
+ }
+
+ @Test
+ public void testTetheringConfigDisable() throws Exception {
+ setupFunctioningNetdInterface();
+ when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(false);
+
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+ coordinator.startPolling();
+
+ // The tether stats polling task should not be scheduled.
+ mTestLooper.moveTimeForward(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
+ waitForIdle();
+ verify(mNetd, never()).tetherOffloadGetStats();
+
+ // The interface name lookup table can't be added.
+ final String iface = "rmnet_data0";
+ final Integer ifIndex = 100;
+ coordinator.addUpstreamNameToLookupTable(ifIndex, iface);
+ assertEquals(0, coordinator.getInterfaceNamesForTesting().size());
+
+ // The rule can't be added.
+ final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
+ final MacAddress mac = MacAddress.fromString("00:00:00:00:00:0a");
+ final Ipv6ForwardingRule rule = buildTestForwardingRule(ifIndex, neigh, mac);
+ coordinator.tetherOffloadRuleAdd(mIpServer, rule);
+ verify(mNetd, never()).tetherOffloadRuleAdd(any());
+ LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules =
+ coordinator.getForwardingRulesForTesting().get(mIpServer);
+ assertNull(rules);
+
+ // The rule can't be removed. This is not a realistic case because adding rule is not
+ // allowed. That implies no rule could be removed, cleared or updated. Verify these
+ // cases just in case.
+ rules = new LinkedHashMap<Inet6Address, Ipv6ForwardingRule>();
+ rules.put(rule.address, rule);
+ coordinator.getForwardingRulesForTesting().put(mIpServer, rules);
+ coordinator.tetherOffloadRuleRemove(mIpServer, rule);
+ verify(mNetd, never()).tetherOffloadRuleRemove(any());
+ rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+
+ // The rule can't be cleared.
+ coordinator.tetherOffloadRuleClear(mIpServer);
+ verify(mNetd, never()).tetherOffloadRuleRemove(any());
+ rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+
+ // The rule can't be updated.
+ coordinator.tetherOffloadRuleUpdate(mIpServer, rule.upstreamIfindex + 1 /* new */);
+ verify(mNetd, never()).tetherOffloadRuleRemove(any());
+ verify(mNetd, never()).tetherOffloadRuleAdd(any());
+ rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
+ assertNotNull(rules);
+ assertEquals(1, rules.size());
+ }
+
+ @Test
+ public void testTetheringConfigSetPollingInterval() throws Exception {
+ setupFunctioningNetdInterface();
+
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+
+ // [1] The default polling interval.
+ coordinator.startPolling();
+ assertEquals(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, coordinator.getPollingInterval());
+ coordinator.stopPolling();
+
+ // [2] Expect the invalid polling interval isn't applied. The valid range of interval is
+ // DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS..max_long.
+ for (final int interval
+ : new int[] {0, 100, DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS - 1}) {
+ when(mTetherConfig.getOffloadPollInterval()).thenReturn(interval);
+ coordinator.startPolling();
+ assertEquals(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, coordinator.getPollingInterval());
+ coordinator.stopPolling();
+ }
+
+ // [3] Set a specific polling interval which is larger than default value.
+ // Use a large polling interval to avoid flaky test because the time forwarding
+ // approximation is used to verify the scheduled time of the polling thread.
+ final int pollingInterval = 100_000;
+ when(mTetherConfig.getOffloadPollInterval()).thenReturn(pollingInterval);
+ coordinator.startPolling();
+
+ // Expect the specific polling interval to be applied.
+ assertEquals(pollingInterval, coordinator.getPollingInterval());
+
+ // Start on a new polling time slot.
+ mTestLooper.moveTimeForward(pollingInterval);
+ waitForIdle();
+ clearInvocations(mNetd);
+
+ // Move time forward to 90% polling interval time. Expect that the polling thread has not
+ // scheduled yet.
+ mTestLooper.moveTimeForward((long) (pollingInterval * 0.9));
+ waitForIdle();
+ verify(mNetd, never()).tetherOffloadGetStats();
+
+ // Move time forward to the remaining 10% polling interval time. Expect that the polling
+ // thread has scheduled.
+ mTestLooper.moveTimeForward((long) (pollingInterval * 0.1));
+ waitForIdle();
+ verify(mNetd).tetherOffloadGetStats();
+ }
}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index 312186391d5f..a9ac4e2851f3 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -294,7 +294,7 @@ public class TetheringConfigurationTest {
initializeBpfOffloadConfiguration(true, null /* unset */);
final TetheringConfiguration enableByRes =
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(enableByRes.enableBpfOffload);
+ assertTrue(enableByRes.isBpfOffloadEnabled());
}
@Test
@@ -303,7 +303,7 @@ public class TetheringConfigurationTest {
initializeBpfOffloadConfiguration(res, "true");
final TetheringConfiguration enableByDevConOverride =
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(enableByDevConOverride.enableBpfOffload);
+ assertTrue(enableByDevConOverride.isBpfOffloadEnabled());
}
}
@@ -312,7 +312,7 @@ public class TetheringConfigurationTest {
initializeBpfOffloadConfiguration(false, null /* unset */);
final TetheringConfiguration disableByRes =
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(disableByRes.enableBpfOffload);
+ assertFalse(disableByRes.isBpfOffloadEnabled());
}
@Test
@@ -321,7 +321,7 @@ public class TetheringConfigurationTest {
initializeBpfOffloadConfiguration(res, "false");
final TetheringConfiguration disableByDevConOverride =
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertFalse(disableByDevConOverride.enableBpfOffload);
+ assertFalse(disableByDevConOverride.isBpfOffloadEnabled());
}
}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index f53c42b7e760..64538c7d97c1 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -40,7 +40,6 @@ import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
-import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -49,6 +48,7 @@ import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
import static com.android.networkstack.tethering.UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES;
@@ -346,8 +346,8 @@ public class TetheringTest {
}
@Override
- public BpfCoordinator getBpfCoordinator(Handler handler, INetd netd,
- SharedLog log, BpfCoordinator.Dependencies deps) {
+ public BpfCoordinator getBpfCoordinator(
+ BpfCoordinator.Dependencies deps) {
return mBpfCoordinator;
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
index 398ece4c1836..19248ca54611 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
@@ -45,6 +45,8 @@ final class AutofillInlineSessionController {
private final Object mLock;
@NonNull
private final Handler mHandler;
+ @NonNull
+ private final InlineFillUi.InlineUiEventCallback mUiCallback;
@Nullable
@GuardedBy("mLock")
@@ -54,12 +56,14 @@ final class AutofillInlineSessionController {
private InlineFillUi mInlineFillUi;
AutofillInlineSessionController(InputMethodManagerInternal inputMethodManagerInternal,
- int userId, ComponentName componentName, Handler handler, Object lock) {
+ int userId, ComponentName componentName, Handler handler, Object lock,
+ InlineFillUi.InlineUiEventCallback callback) {
mInputMethodManagerInternal = inputMethodManagerInternal;
mUserId = userId;
mComponentName = componentName;
mHandler = handler;
mLock = lock;
+ mUiCallback = callback;
}
@@ -82,7 +86,8 @@ final class AutofillInlineSessionController {
// TODO(b/151123764): consider reusing the same AutofillInlineSession object for the
// same field.
mSession = new AutofillInlineSuggestionsRequestSession(mInputMethodManagerInternal, mUserId,
- mComponentName, mHandler, mLock, autofillId, requestConsumer, uiExtras);
+ mComponentName, mHandler, mLock, autofillId, requestConsumer, uiExtras,
+ mUiCallback);
mSession.onCreateInlineSuggestionsRequestLocked();
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
index 48895ad42e99..68eeb0a3ca2e 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
@@ -29,6 +29,7 @@ import android.os.Handler;
import android.os.RemoteException;
import android.util.Slog;
import android.view.autofill.AutofillId;
+import android.view.inputmethod.InlineSuggestion;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;
@@ -40,6 +41,7 @@ import com.android.server.autofill.ui.InlineFillUi;
import com.android.server.inputmethod.InputMethodManagerInternal;
import java.lang.ref.WeakReference;
+import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
@@ -65,6 +67,8 @@ final class AutofillInlineSuggestionsRequestSession {
private final Handler mHandler;
@NonNull
private final Bundle mUiExtras;
+ @NonNull
+ private final InlineFillUi.InlineUiEventCallback mUiCallback;
@GuardedBy("mLock")
@NonNull
@@ -97,18 +101,22 @@ final class AutofillInlineSuggestionsRequestSession {
@GuardedBy("mLock")
private boolean mDestroyed = false;
+ @GuardedBy("mLock")
+ private boolean mPreviousHasNonPinSuggestionShow;
AutofillInlineSuggestionsRequestSession(
@NonNull InputMethodManagerInternal inputMethodManagerInternal, int userId,
@NonNull ComponentName componentName, @NonNull Handler handler, @NonNull Object lock,
@NonNull AutofillId autofillId,
- @NonNull Consumer<InlineSuggestionsRequest> requestConsumer, @NonNull Bundle uiExtras) {
+ @NonNull Consumer<InlineSuggestionsRequest> requestConsumer, @NonNull Bundle uiExtras,
+ @NonNull InlineFillUi.InlineUiEventCallback callback) {
mInputMethodManagerInternal = inputMethodManagerInternal;
mUserId = userId;
mComponentName = componentName;
mHandler = handler;
mLock = lock;
mUiExtras = uiExtras;
+ mUiCallback = callback;
mAutofillId = autofillId;
mImeRequestConsumer = requestConsumer;
@@ -217,6 +225,7 @@ final class AutofillInlineSuggestionsRequestSession {
// No-op if both the previous response and current response are empty.
return;
}
+ maybeNotifyFillUiEventLocked(response.getInlineSuggestions());
updateResponseToImeUncheckLocked(response);
mPreviousResponseIsNotEmpty = !isEmptyResponse;
}
@@ -238,6 +247,38 @@ final class AutofillInlineSuggestionsRequestSession {
}
}
+ @GuardedBy("mLock")
+ private void maybeNotifyFillUiEventLocked(@NonNull List<InlineSuggestion> suggestions) {
+ if (mDestroyed) {
+ return;
+ }
+ boolean hasSuggestionToShow = false;
+ for (int i = 0; i < suggestions.size(); i++) {
+ InlineSuggestion suggestion = suggestions.get(i);
+ // It is possible we don't have any match result but we still have pinned
+ // suggestions. Only notify we have non-pinned suggestions to show
+ if (!suggestion.getInfo().isPinned()) {
+ hasSuggestionToShow = true;
+ break;
+ }
+ }
+ if (sDebug) {
+ Slog.d(TAG, "maybeNotifyFillUiEventLoked(): hasSuggestionToShow=" + hasSuggestionToShow
+ + ", mPreviousHasNonPinSuggestionShow=" + mPreviousHasNonPinSuggestionShow);
+ }
+ // Use mPreviousHasNonPinSuggestionShow to save previous status, if the display status
+ // change, we can notify the event.
+ if (hasSuggestionToShow && !mPreviousHasNonPinSuggestionShow) {
+ // From no suggestion to has suggestions to show
+ mUiCallback.notifyInlineUiShown(mAutofillId);
+ } else if (!hasSuggestionToShow && mPreviousHasNonPinSuggestionShow) {
+ // From has suggestions to no suggestions to show
+ mUiCallback.notifyInlineUiHidden(mAutofillId);
+ }
+ // Update the latest status
+ mPreviousHasNonPinSuggestionShow = hasSuggestionToShow;
+ }
+
/**
* Handles the {@code request} and {@code callback} received from the IME.
*
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 4e0970f1e40b..11f901538868 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -167,14 +167,16 @@ final class RemoteAugmentedAutofillService
new IFillCallback.Stub() {
@Override
public void onSuccess(@Nullable List<Dataset> inlineSuggestionsData,
- @Nullable Bundle clientState) {
+ @Nullable Bundle clientState, boolean showingFillWindow) {
mCallbacks.resetLastResponse();
maybeRequestShowInlineSuggestions(sessionId,
inlineSuggestionsRequest, inlineSuggestionsData,
clientState, focusedId, focusedValue,
inlineSuggestionsCallback,
client, onErrorCallback, remoteRenderService);
- requestAutofill.complete(null);
+ if (!showingFillWindow) {
+ requestAutofill.complete(null);
+ }
}
@Override
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 158ed8ca6906..3114a6a02e31 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -843,7 +843,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
setClientLocked(client);
mInlineSessionController = new AutofillInlineSessionController(inputMethodManagerInternal,
- userId, componentName, handler, mLock);
+ userId, componentName, handler, mLock,
+ new InlineFillUi.InlineUiEventCallback() {
+ @Override
+ public void notifyInlineUiShown(AutofillId autofillId) {
+ notifyFillUiShown(autofillId);
+ }
+
+ @Override
+ public void notifyInlineUiHidden(AutofillId autofillId) {
+ notifyFillUiHidden(autofillId);
+ }
+ });
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
@@ -1329,6 +1340,26 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
this, intentSender, intent));
}
+ private void notifyFillUiHidden(@NonNull AutofillId autofillId) {
+ synchronized (mLock) {
+ try {
+ mClient.notifyFillUiHidden(this.id, autofillId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error sending fill UI hidden notification", e);
+ }
+ }
+ }
+
+ private void notifyFillUiShown(@NonNull AutofillId autofillId) {
+ synchronized (mLock) {
+ try {
+ mClient.notifyFillUiShown(this.id, autofillId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error sending fill UI shown notification", e);
+ }
+ }
+ }
+
private void doStartIntentSender(IntentSender intentSender, Intent intent) {
try {
synchronized (mLock) {
@@ -2769,11 +2800,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// TODO(b/156099633): remove this once framework gets out of business of resending
// inline suggestions when IME visibility changes.
mInlineSessionController.hideInlineSuggestionsUiLocked(viewState.id);
- try {
- mClient.notifyFillUiHidden(this.id, viewState.id);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error requesting to hide fill UI", e);
- }
viewState.resetState(ViewState.STATE_CHANGED);
return;
} else if ((viewState.id.equals(this.mCurrentViewId))
@@ -2800,11 +2826,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// TODO: we should be able to replace this with controller#filterInlineFillUiLocked
// to accomplish filtering for augmented autofill.
mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId);
- try {
- mClient.notifyFillUiHidden(this.id, mCurrentViewId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error sending fill UI hidden notification", e);
- }
}
}
@@ -2890,11 +2911,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (requestShowInlineSuggestionsLocked(response, filterText)) {
final ViewState currentView = mViewStates.get(mCurrentViewId);
currentView.setState(ViewState.STATE_INLINE_SHOWN);
- try {
- mClient.notifyFillUiShown(this.id, mCurrentViewId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error sending fill UI shown notification", e);
- }
//TODO(b/137800469): Fix it to log showed only when IME asks for inflation,
// rather than here where framework sends back the response.
mService.logDatasetShown(id, mClientState);
@@ -2965,11 +2981,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
synchronized (mLock) {
mInlineSessionController.hideInlineSuggestionsUiLocked(
focusedId);
- try {
- mClient.notifyFillUiHidden(this.id, focusedId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error sending fill UI hidden notification", e);
- }
}
}, remoteRenderService);
return mInlineSessionController.setInlineFillUiLocked(inlineFillUi);
@@ -3279,16 +3290,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
};
// When the inline suggestion render service is available and the view is focused, there
- // are 2 cases when augmented autofill should ask IME for inline suggestion request,
+ // are 3 cases when augmented autofill should ask IME for inline suggestion request,
// because standard autofill flow didn't:
// 1. the field is augmented autofill only (when standard autofill provider is None or
// when it returns null response)
// 2. standard autofill provider doesn't support inline suggestion
+ // 3. we re-entered the autofill session and standard autofill was not re-triggered, this is
+ // recognized by seeing mExpiredResponse == true
final RemoteInlineSuggestionRenderService remoteRenderService =
mService.getRemoteInlineSuggestionRenderServiceLocked();
if (remoteRenderService != null
&& (mForAugmentedAutofillOnly
- || !isInlineSuggestionsEnabledByAutofillProviderLocked())
+ || !isInlineSuggestionsEnabledByAutofillProviderLocked()
+ || mExpiredResponse)
&& isViewFocusedLocked(flags)) {
if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
remoteRenderService.getInlineSuggestionsRendererInfo(new RemoteCallback(
@@ -3481,11 +3495,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
if (mCurrentViewId != null) {
mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId);
- try {
- mClient.notifyFillUiHidden(this.id, mCurrentViewId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error sending fill UI hidden notification", e);
- }
}
autoFillApp(dataset);
return;
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java b/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
index 1c430b3543ac..627c0733b078 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
@@ -297,4 +297,19 @@ public final class InlineFillUi {
*/
void startIntentSender(@NonNull IntentSender intentSender, @NonNull Intent intent);
}
+
+ /**
+ * Callback for inline suggestion Ui related events.
+ */
+ public interface InlineUiEventCallback {
+ /**
+ * Callback to notify inline ui is shown.
+ */
+ void notifyInlineUiShown(@NonNull AutofillId autofillId);
+
+ /**
+ * Callback to notify inline ui is hidden.
+ */
+ void notifyInlineUiHidden(@NonNull AutofillId autofillId);
+ }
}
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngineThread.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngineThread.java
index 7075608674a1..71f1dbf35008 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngineThread.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngineThread.java
@@ -1,10 +1,10 @@
package com.android.server.backup.restore;
import android.os.ParcelFileDescriptor;
+import android.os.ParcelFileDescriptor.AutoCloseInputStream;
import libcore.io.IoUtils;
-import java.io.FileInputStream;
import java.io.InputStream;
class FullRestoreEngineThread implements Runnable {
@@ -19,7 +19,7 @@ class FullRestoreEngineThread implements Runnable {
// We *do* want this FileInputStream to own the underlying fd, so that
// when we are finished with it, it closes this end of the pipe in a way
// that signals its other end.
- mEngineStream = new FileInputStream(engineSocket.getFileDescriptor(), true);
+ mEngineStream = new AutoCloseInputStream(engineSocket);
// Tell it to be sure to leave the agent instance up after finishing
mMustKillAgent = false;
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 961dc159009c..6859c5835c80 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -222,6 +222,9 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
try {
Set<Association> associations = readAllAssociations(userId);
+ if (associations == null) {
+ continue;
+ }
for (Association a : associations) {
try {
int uid = pm.getPackageUidAsUser(a.companionAppPackage, userId);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 4a4b7dd7cc29..ea94ad0b3c20 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -953,7 +953,7 @@ public final class ContentCaptureManagerService extends
}
@Override
- public void accept(@NonNull IDataShareReadAdapter serviceAdapter) throws RemoteException {
+ public void accept(@NonNull IDataShareReadAdapter serviceAdapter) {
Slog.i(TAG, "Data share request accepted by Content Capture service");
logServiceEvent(CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ACCEPT_DATA_SHARE_REQUEST);
@@ -961,8 +961,8 @@ public final class ContentCaptureManagerService extends
if (clientPipe == null) {
logServiceEvent(
CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL);
- mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
- serviceAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+ sendErrorSignal(mClientAdapter, serviceAdapter,
+ ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
return;
}
@@ -975,8 +975,8 @@ public final class ContentCaptureManagerService extends
CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL);
bestEffortCloseFileDescriptors(sourceIn, sinkIn);
- mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
- serviceAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+ sendErrorSignal(mClientAdapter, serviceAdapter,
+ ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
return;
}
@@ -985,8 +985,26 @@ public final class ContentCaptureManagerService extends
mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
- mClientAdapter.write(sourceIn);
- serviceAdapter.start(sinkOut);
+ try {
+ mClientAdapter.write(sourceIn);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to call write() the client operation", e);
+ sendErrorSignal(mClientAdapter, serviceAdapter,
+ ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+ logServiceEvent(
+ CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL);
+ return;
+ }
+ try {
+ serviceAdapter.start(sinkOut);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to call start() the service operation", e);
+ sendErrorSignal(mClientAdapter, serviceAdapter,
+ ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+ logServiceEvent(
+ CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL);
+ return;
+ }
// File descriptors received by remote apps will be copies of the current one. Close
// the ones that belong to the system server, so there's only 1 open left for the
@@ -1061,11 +1079,20 @@ public final class ContentCaptureManagerService extends
}
@Override
- public void reject() throws RemoteException {
+ public void reject() {
Slog.i(TAG, "Data share request rejected by Content Capture service");
logServiceEvent(CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__REJECT_DATA_SHARE_REQUEST);
- mClientAdapter.rejected();
+ try {
+ mClientAdapter.rejected();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call rejected() the client operation", e);
+ try {
+ mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+ } catch (RemoteException e2) {
+ Slog.w(TAG, "Failed to call error() the client operation", e2);
+ }
+ }
}
private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn,
diff --git a/services/core/java/android/os/UserManagerInternal.java b/services/core/java/android/os/UserManagerInternal.java
index 94f5741fe828..fbe8c04bd59c 100644
--- a/services/core/java/android/os/UserManagerInternal.java
+++ b/services/core/java/android/os/UserManagerInternal.java
@@ -27,6 +27,7 @@ import com.android.server.pm.RestrictionsSet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.List;
/**
* @hide Only for use within the system server.
@@ -219,6 +220,13 @@ public abstract class UserManagerInternal {
public abstract int[] getUserIds();
/**
+ * Internal implementation of getUsers does not check permissions.
+ * This improves performance for calls from inside system server which already have permissions
+ * checked.
+ */
+ public abstract @NonNull List<UserInfo> getUsers(boolean excludeDying);
+
+ /**
* Checks if the {@code callingUserId} and {@code targetUserId} are same or in same group
* and that the {@code callingUserId} is not a profile and {@code targetUserId} is enabled.
*
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 1ce3dfe9f3a0..b46bebbd03d5 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -52,7 +52,6 @@ import static com.android.internal.util.XmlUtils.readStringAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
-import static com.android.server.storage.StorageUserConnection.REMOTE_TIMEOUT_SECONDS;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -224,6 +223,9 @@ class StorageManagerService extends IStorageManager.Stub
private static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
"persist.sys.vold_app_data_isolation_enabled";
+ // How long we wait to reset storage, if we failed to call onMount on the
+ // external storage service.
+ public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10;
/**
* If {@code 1}, enables the isolated storage feature. If {@code -1},
* disables the isolated storage feature. If {@code 0}, uses the default
@@ -1083,7 +1085,12 @@ class StorageManagerService extends IStorageManager.Stub
final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
if (mIsFuseEnabled) {
- mStorageSessionController.onReset(mVold, mHandler);
+ mStorageSessionController.onReset(mVold, () -> {
+ mHandler.removeMessages(H_RESET);
+ mHandler.removeMessages(H_VOLUME_BROADCAST);
+ mHandler.removeMessages(H_VOLUME_MOUNT);
+ mHandler.removeMessages(H_VOLUME_UNMOUNT);
+ });
} else {
killMediaProvider(users);
}
@@ -1134,8 +1141,6 @@ class StorageManagerService extends IStorageManager.Stub
Slog.wtf(TAG, e);
}
- onKeyguardStateChanged(false);
-
mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
}
@@ -1147,6 +1152,8 @@ class StorageManagerService extends IStorageManager.Stub
mPmInternal.migrateLegacyObbData();
}
+ onKeyguardStateChanged(false);
+
// Record user as started so newly mounted volumes kick off events
// correctly, then synthesize events for any already-mounted volumes.
synchronized (mLock) {
@@ -2202,7 +2209,7 @@ class StorageManagerService extends IStorageManager.Stub
} catch (ExternalStorageServiceException e) {
Slog.e(TAG, "Failed to mount volume " + vol, e);
- int nextResetSeconds = REMOTE_TIMEOUT_SECONDS * 2;
+ int nextResetSeconds = FAILED_MOUNT_RESET_TIMEOUT_SECONDS;
Slog.i(TAG, "Scheduling reset in " + nextResetSeconds + "s");
mHandler.removeMessages(H_RESET);
mHandler.sendMessageDelayed(mHandler.obtainMessage(H_RESET),
@@ -2252,8 +2259,15 @@ class StorageManagerService extends IStorageManager.Stub
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
+ final String fsUuid = vol.fsUuid;
try {
mVold.format(vol.id, "auto");
+
+ // After a successful format above, we should forget about any
+ // records for the old partition, since it'll never appear again
+ if (!TextUtils.isEmpty(fsUuid)) {
+ forgetVolume(fsUuid);
+ }
} catch (Exception e) {
Slog.wtf(TAG, e);
}
@@ -3535,6 +3549,13 @@ class StorageManagerService extends IStorageManager.Stub
// point
final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
+ // When the caller is the app actually hosting external storage, we
+ // should never attempt to augment the actual storage volume state,
+ // otherwise we risk confusing it with race conditions as users go
+ // through various unlocked states
+ final boolean callerIsMediaStore = UserHandle.isSameApp(Binder.getCallingUid(),
+ mMediaStoreAuthorityAppId);
+
final boolean userIsDemo;
final boolean userKeyUnlocked;
final boolean storagePermission;
@@ -3554,6 +3575,7 @@ class StorageManagerService extends IStorageManager.Stub
final ArraySet<String> resUuids = new ArraySet<>();
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
+ final String volId = mVolumes.keyAt(i);
final VolumeInfo vol = mVolumes.valueAt(i);
switch (vol.getType()) {
case VolumeInfo.TYPE_PUBLIC:
@@ -3578,11 +3600,19 @@ class StorageManagerService extends IStorageManager.Stub
if (!match) continue;
boolean reportUnmounted = false;
- if (!systemUserUnlocked) {
+ if (callerIsMediaStore) {
+ // When the caller is the app actually hosting external storage, we
+ // should never attempt to augment the actual storage volume state,
+ // otherwise we risk confusing it with race conditions as users go
+ // through various unlocked states
+ } else if (!systemUserUnlocked) {
reportUnmounted = true;
+ Slog.w(TAG, "Reporting " + volId + " unmounted due to system locked");
} else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
reportUnmounted = true;
+ Slog.w(TAG, "Reporting " + volId + "unmounted due to " + userId + " locked");
} else if (!storagePermission && !realState) {
+ Slog.w(TAG, "Reporting " + volId + "unmounted due to missing permissions");
reportUnmounted = true;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 133ea8394ba6..20adfa5438cb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1671,12 +1671,6 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
@Nullable ContentCaptureManagerInternal mContentCaptureService;
- /**
- * Set of {@link ProcessRecord} that have either {@link ProcessRecord#hasTopUi()} or
- * {@link ProcessRecord#runningRemoteAnimation} set to {@code true}.
- */
- final ArraySet<ProcessRecord> mTopUiOrRunningRemoteAnimApps = new ArraySet<>();
-
final class UiHandler extends Handler {
public UiHandler() {
super(com.android.server.UiThread.get().getLooper(), null, true);
@@ -14708,7 +14702,6 @@ public class ActivityManagerService extends IActivityManager.Stub
mProcessesToGc.remove(app);
mPendingPssProcesses.remove(app);
- mTopUiOrRunningRemoteAnimApps.remove(app);
ProcessList.abortNextPssTime(app.procStateMemTracker);
// Dismiss any open dialogs.
@@ -15788,9 +15781,10 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (receivers != null && broadcastWhitelist != null) {
for (int i = receivers.size() - 1; i >= 0; i--) {
- final int uid = receivers.get(i).activityInfo.applicationInfo.uid;
- if (uid >= Process.FIRST_APPLICATION_UID
- && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
+ final int receiverAppId = UserHandle.getAppId(
+ receivers.get(i).activityInfo.applicationInfo.uid);
+ if (receiverAppId >= Process.FIRST_APPLICATION_UID
+ && Arrays.binarySearch(broadcastWhitelist, receiverAppId) < 0) {
receivers.remove(i);
}
}
@@ -16436,9 +16430,9 @@ public class ActivityManagerService extends IActivityManager.Stub
// if a uid whitelist was provided, remove anything in the application space that wasn't
// in it.
for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
- final int uid = registeredReceivers.get(i).owningUid;
- if (uid >= Process.FIRST_APPLICATION_UID
- && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
+ final int owningAppId = UserHandle.getAppId(registeredReceivers.get(i).owningUid);
+ if (owningAppId >= Process.FIRST_APPLICATION_UID
+ && Arrays.binarySearch(broadcastWhitelist, owningAppId) < 0) {
registeredReceivers.remove(i);
}
}
@@ -18508,22 +18502,6 @@ public class ActivityManagerService extends IActivityManager.Stub
return proc;
}
- /**
- * @return {@code true} if {@link #mTopUiOrRunningRemoteAnimApps} set contains {@code app} or when there are no apps
- * in this list, an false otherwise.
- */
- boolean containsTopUiOrRunningRemoteAnimOrEmptyLocked(ProcessRecord app) {
- return mTopUiOrRunningRemoteAnimApps.isEmpty() || mTopUiOrRunningRemoteAnimApps.contains(app);
- }
-
- void addTopUiOrRunningRemoteAnim(ProcessRecord app) {
- mTopUiOrRunningRemoteAnimApps.add(app);
- }
-
- void removeTopUiOrRunningRemoteAnim(ProcessRecord app) {
- mTopUiOrRunningRemoteAnimApps.remove(app);
- }
-
@Override
public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
boolean runGc, String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 58b0a157e2c2..da5f48962130 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1151,17 +1151,8 @@ public final class OomAdjuster {
// is currently showing UI.
app.systemNoUi = true;
if (app == topApp) {
- // If specific system app has set ProcessRecord.mHasTopUi or is running a remote
- // animation (ProcessRecord.runningRemoteAnimation), this will prevent topApp
- // to use SCHED_GROUP_TOP_APP to ensure process with mHasTopUi will have exclusive
- // access to configured cores.
- if (mService.containsTopUiOrRunningRemoteAnimOrEmptyLocked(app)) {
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
- } else {
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
- }
app.systemNoUi = false;
-
+ app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
app.adjType = "pers-top-activity";
} else if (app.hasTopUi()) {
// sched group/proc state adjustment is below
@@ -1202,20 +1193,10 @@ public final class OomAdjuster {
boolean foregroundActivities = false;
if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
-
- // If specific system app has set ProcessRecord.mHasTopUi or is running a remote
- // animation (ProcessRecord.runningRemoteAnimation), this will prevent topApp
- // to use SCHED_GROUP_TOP_APP to ensure process with mHasTopUi will have exclusive
- // access to configured cores.
- if (mService.containsTopUiOrRunningRemoteAnimOrEmptyLocked(app)) {
- adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
- app.adjType = "top-activity";
- } else {
- adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
- app.adjType = "top-activity-behind-topui";
- }
+ // The last app on the list is the foreground app.
+ adj = ProcessList.FOREGROUND_APP_ADJ;
+ schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
+ app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 4c75ab21d6f2..c5152c081e70 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1268,7 +1268,6 @@ class ProcessRecord implements WindowProcessListener {
void setHasTopUi(boolean hasTopUi) {
mHasTopUi = hasTopUi;
mWindowProcessController.setHasTopUi(hasTopUi);
- updateTopUiOrRunningRemoteAnim();
}
boolean hasTopUi() {
@@ -1519,19 +1518,10 @@ class ProcessRecord implements WindowProcessListener {
Slog.i(TAG, "Setting runningRemoteAnimation=" + runningRemoteAnimation
+ " for pid=" + pid);
}
- updateTopUiOrRunningRemoteAnim();
mService.updateOomAdjLocked(this, true, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
}
}
- void updateTopUiOrRunningRemoteAnim() {
- if (runningRemoteAnimation || hasTopUi()) {
- mService.addTopUiOrRunningRemoteAnim(this);
- } else {
- mService.removeTopUiOrRunningRemoteAnim(this);
- }
- }
-
public long getInputDispatchingTimeout() {
return mWindowProcessController.getInputDispatchingTimeout();
}
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 769956d797b0..e3eeb6c41d9f 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -47,6 +47,10 @@ import android.service.dreams.IDreamManager;
import android.util.Slog;
import android.view.Display;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.util.DumpUtils;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -77,6 +81,8 @@ public final class DreamManagerService extends SystemService {
private final PowerManagerInternal mPowerManagerInternal;
private final PowerManager.WakeLock mDozeWakeLock;
private final ActivityTaskManagerInternal mAtmInternal;
+ private final UiEventLogger mUiEventLogger;
+ private final ComponentName mAmbientDisplayComponent;
private Binder mCurrentDreamToken;
private ComponentName mCurrentDreamName;
@@ -91,6 +97,26 @@ public final class DreamManagerService extends SystemService {
private AmbientDisplayConfiguration mDozeConfig;
+ @VisibleForTesting
+ public enum DreamManagerEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "The screensaver has started.")
+ DREAM_START(577),
+
+ @UiEvent(doc = "The screensaver has stopped.")
+ DREAM_STOP(578);
+
+ private final int mId;
+
+ DreamManagerEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+ }
+
public DreamManagerService(Context context) {
super(context);
mContext = context;
@@ -102,6 +128,9 @@ public final class DreamManagerService extends SystemService {
mAtmInternal = getLocalService(ActivityTaskManagerInternal.class);
mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
mDozeConfig = new AmbientDisplayConfiguration(mContext);
+ mUiEventLogger = new UiEventLoggerImpl();
+ AmbientDisplayConfiguration adc = new AmbientDisplayConfiguration(mContext);
+ mAmbientDisplayComponent = ComponentName.unflattenFromString(adc.ambientDisplayComponent());
}
@Override
@@ -388,6 +417,9 @@ public final class DreamManagerService extends SystemService {
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
mHandler.post(wakeLock.wrap(() -> {
mAtmInternal.notifyDreamStateChanged(true);
+ if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
+ mUiEventLogger.log(DreamManagerEvent.DREAM_START);
+ }
mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock);
}));
}
@@ -415,6 +447,9 @@ public final class DreamManagerService extends SystemService {
}
private void cleanupDreamLocked() {
+ if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
+ mUiEventLogger.log(DreamManagerEvent.DREAM_STOP);
+ }
mCurrentDreamToken = null;
mCurrentDreamName = null;
mCurrentDreamIsTest = false;
diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java
index 955f17781540..8a3c963f4805 100644
--- a/services/core/java/com/android/server/gpu/GpuService.java
+++ b/services/core/java/com/android/server/gpu/GpuService.java
@@ -39,6 +39,7 @@ import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.Base64;
import android.util.Slog;
@@ -62,15 +63,19 @@ public class GpuService extends SystemService {
public static final String TAG = "GpuService";
public static final boolean DEBUG = false;
- private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
+ private static final String PROD_DRIVER_PROPERTY = "ro.gfx.driver.0";
+ private static final String DEV_DRIVER_PROPERTY = "ro.gfx.driver.1";
private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt";
private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP;
private final Context mContext;
- private final String mDriverPackageName;
+ private final String mProdDriverPackageName;
+ private final String mDevDriverPackageName;
private final PackageManager mPackageManager;
private final Object mLock = new Object();
private final Object mDeviceConfigLock = new Object();
+ private final boolean mHasProdDriver;
+ private final boolean mHasDevDriver;
private ContentResolver mContentResolver;
private long mGameDriverVersionCode;
private SettingsObserver mSettingsObserver;
@@ -82,10 +87,13 @@ public class GpuService extends SystemService {
super(context);
mContext = context;
- mDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
+ mProdDriverPackageName = SystemProperties.get(PROD_DRIVER_PROPERTY);
mGameDriverVersionCode = -1;
+ mDevDriverPackageName = SystemProperties.get(DEV_DRIVER_PROPERTY);
mPackageManager = context.getPackageManager();
- if (mDriverPackageName != null && !mDriverPackageName.isEmpty()) {
+ mHasProdDriver = !TextUtils.isEmpty(mProdDriverPackageName);
+ mHasDevDriver = !TextUtils.isEmpty(mDevDriverPackageName);
+ if (mHasDevDriver || mHasProdDriver) {
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(ACTION_PACKAGE_ADDED);
packageFilter.addAction(ACTION_PACKAGE_CHANGED);
@@ -104,7 +112,7 @@ public class GpuService extends SystemService {
public void onBootPhase(int phase) {
if (phase == PHASE_BOOT_COMPLETED) {
mContentResolver = mContext.getContentResolver();
- if (mDriverPackageName == null || mDriverPackageName.isEmpty()) {
+ if (!mHasProdDriver && !mHasDevDriver) {
return;
}
mSettingsObserver = new SettingsObserver();
@@ -112,6 +120,7 @@ public class GpuService extends SystemService {
fetchGameDriverPackageProperties();
processBlacklists();
setBlacklist();
+ fetchDeveloperDriverPackageProperties();
}
}
@@ -166,18 +175,22 @@ public class GpuService extends SystemService {
return;
}
final String packageName = data.getSchemeSpecificPart();
- if (!packageName.equals(mDriverPackageName)) {
+ final boolean isProdDriver = packageName.equals(mProdDriverPackageName);
+ final boolean isDevDriver = packageName.equals(mDevDriverPackageName);
+ if (!isProdDriver && !isDevDriver) {
return;
}
- final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-
switch (intent.getAction()) {
case ACTION_PACKAGE_ADDED:
case ACTION_PACKAGE_CHANGED:
case ACTION_PACKAGE_REMOVED:
- fetchGameDriverPackageProperties();
- setBlacklist();
+ if (isProdDriver) {
+ fetchGameDriverPackageProperties();
+ setBlacklist();
+ } else if (isDevDriver) {
+ fetchDeveloperDriverPackageProperties();
+ }
break;
default:
// do nothing
@@ -208,11 +221,11 @@ public class GpuService extends SystemService {
private void fetchGameDriverPackageProperties() {
final ApplicationInfo driverInfo;
try {
- driverInfo = mPackageManager.getApplicationInfo(mDriverPackageName,
+ driverInfo = mPackageManager.getApplicationInfo(mProdDriverPackageName,
PackageManager.MATCH_SYSTEM_ONLY);
} catch (PackageManager.NameNotFoundException e) {
if (DEBUG) {
- Slog.e(TAG, "driver package '" + mDriverPackageName + "' not installed");
+ Slog.e(TAG, "driver package '" + mProdDriverPackageName + "' not installed");
}
return;
}
@@ -232,14 +245,14 @@ public class GpuService extends SystemService {
mGameDriverVersionCode = driverInfo.longVersionCode;
try {
- final Context driverContext = mContext.createPackageContext(mDriverPackageName,
+ final Context driverContext = mContext.createPackageContext(mProdDriverPackageName,
Context.CONTEXT_RESTRICTED);
assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_WHITELIST_FILENAME,
Settings.Global.GAME_DRIVER_WHITELIST, ",");
} catch (PackageManager.NameNotFoundException e) {
if (DEBUG) {
- Slog.w(TAG, "driver package '" + mDriverPackageName + "' not installed");
+ Slog.w(TAG, "driver package '" + mProdDriverPackageName + "' not installed");
}
}
}
@@ -291,4 +304,40 @@ public class GpuService extends SystemService {
}
}
}
+
+ private void fetchDeveloperDriverPackageProperties() {
+ final ApplicationInfo driverInfo;
+ try {
+ driverInfo = mPackageManager.getApplicationInfo(mDevDriverPackageName,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ } catch (PackageManager.NameNotFoundException e) {
+ if (DEBUG) {
+ Slog.e(TAG, "driver package '" + mDevDriverPackageName + "' not installed");
+ }
+ return;
+ }
+
+ // O drivers are restricted to the sphal linker namespace, so don't try to use
+ // packages unless they declare they're compatible with that restriction.
+ if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+ if (DEBUG) {
+ Slog.w(TAG, "Driver package is not known to be compatible with O");
+ }
+ return;
+ }
+
+ setUpdatableDriverPath(driverInfo);
+ }
+
+ private void setUpdatableDriverPath(ApplicationInfo ai) {
+ if (ai.primaryCpuAbi == null) {
+ nSetUpdatableDriverPath("");
+ return;
+ }
+ final StringBuilder sb = new StringBuilder();
+ sb.append(ai.sourceDir).append("!/lib/");
+ nSetUpdatableDriverPath(sb.toString());
+ }
+
+ private static native void nSetUpdatableDriverPath(String driverPath);
}
diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
index e17cca423822..3fb713bc01a5 100644
--- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
@@ -17,9 +17,8 @@
package com.android.server.location.gnss;
import android.content.Context;
+import android.database.Cursor;
import android.net.ConnectivityManager;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
@@ -27,26 +26,25 @@ import android.net.NetworkRequest;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
-import android.telephony.PhoneStateListener;
-import android.telephony.PreciseCallState;
+import android.provider.Telephony.Carriers;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
+import android.telephony.PreciseCallState;
+import android.telephony.PhoneStateListener;
import android.util.Log;
import com.android.internal.location.GpsNetInitiatedHandler;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
+import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-
+import java.util.Iterator;
/**
* Handles network connection requests and network state change updates for AGPS data download.
@@ -387,10 +385,10 @@ class GnssNetworkConnectivityHandler {
private ConnectivityManager.NetworkCallback createSuplConnectivityCallback() {
return new ConnectivityManager.NetworkCallback() {
@Override
- public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
+ public void onAvailable(Network network) {
if (DEBUG) Log.d(TAG, "SUPL network connection available.");
// Specific to a change to a SUPL enabled network becoming ready
- handleSuplConnectionAvailable(network, linkProperties);
+ handleSuplConnectionAvailable(network);
}
@Override
@@ -498,7 +496,7 @@ class GnssNetworkConnectivityHandler {
return networkAttributes;
}
- private void handleSuplConnectionAvailable(Network network, LinkProperties linkProperties) {
+ private void handleSuplConnectionAvailable(Network network) {
// TODO: The synchronous method ConnectivityManager.getNetworkInfo() should not be called
// inside the asynchronous ConnectivityManager.NetworkCallback methods.
NetworkInfo info = mConnMgr.getNetworkInfo(network);
@@ -530,7 +528,7 @@ class GnssNetworkConnectivityHandler {
setRouting();
}
- int apnIpType = getLinkIpType(linkProperties);
+ int apnIpType = getApnIpType(apn);
if (DEBUG) {
String message = String.format(
"native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
@@ -706,32 +704,74 @@ class GnssNetworkConnectivityHandler {
}
}
- private int getLinkIpType(LinkProperties linkProperties) {
+ private int getApnIpType(String apn) {
ensureInHandlerThread();
- boolean isIPv4 = false;
- boolean isIPv6 = false;
-
- List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
- for (LinkAddress linkAddress : linkAddresses) {
- InetAddress inetAddress = linkAddress.getAddress();
- if (inetAddress instanceof Inet4Address) {
- isIPv4 = true;
- } else if (inetAddress instanceof Inet6Address) {
- isIPv6 = true;
+ if (apn == null) {
+ return APN_INVALID;
+ }
+ TelephonyManager phone = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ // During an emergency call with an active sub id, get the Telephony Manager specific
+ // to the active sub to get the correct value from getServiceState and getNetworkType
+ if (mNiHandler.getInEmergency() && mActiveSubId >= 0) {
+ TelephonyManager subIdTelManager =
+ phone.createForSubscriptionId(mActiveSubId);
+ if (subIdTelManager != null) {
+ phone = subIdTelManager;
}
- if (DEBUG) Log.d(TAG, "LinkAddress : " + inetAddress.toString());
}
-
- if (isIPv4 && isIPv6) {
- return APN_IPV4V6;
+ ServiceState serviceState = phone.getServiceState();
+ String projection = null;
+ String selection = null;
+
+ // Carrier configuration may override framework roaming state, we need to use the actual
+ // modem roaming state instead of the framework roaming state.
+ if (serviceState != null && serviceState.getDataRoamingFromRegistration()) {
+ projection = Carriers.ROAMING_PROTOCOL;
+ } else {
+ projection = Carriers.PROTOCOL;
+ }
+ // No SIM case for emergency
+ if (TelephonyManager.NETWORK_TYPE_UNKNOWN == phone.getNetworkType()
+ && AGPS_TYPE_EIMS == mAGpsType) {
+ selection = String.format(
+ "type like '%%emergency%%' and apn = '%s' and carrier_enabled = 1", apn);
+ } else {
+ selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
+ }
+ try (Cursor cursor = mContext.getContentResolver().query(
+ Carriers.CONTENT_URI,
+ new String[]{projection},
+ selection,
+ null,
+ Carriers.DEFAULT_SORT_ORDER)) {
+ if (null != cursor && cursor.moveToFirst()) {
+ return translateToApnIpType(cursor.getString(0), apn);
+ } else {
+ Log.e(TAG, "No entry found in query for APN: " + apn);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error encountered on APN query for: " + apn, e);
}
- if (isIPv4) {
+
+ return APN_IPV4V6;
+ }
+
+ private int translateToApnIpType(String ipProtocol, String apn) {
+ if ("IP".equals(ipProtocol)) {
return APN_IPV4;
}
- if (isIPv6) {
+ if ("IPV6".equals(ipProtocol)) {
return APN_IPV6;
}
- return APN_INVALID;
+ if ("IPV4V6".equals(ipProtocol)) {
+ return APN_IPV4V6;
+ }
+
+ // we hit the default case so the ipProtocol is not recognized
+ String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
+ Log.e(TAG, message);
+ return APN_IPV4V6;
}
// AGPS support
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index c7575d4fc8a4..4def7db76bc5 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -52,6 +52,7 @@ class BluetoothRouteProvider {
private static BluetoothRouteProvider sInstance;
@SuppressWarnings("WeakerAccess") /* synthetic access */
+ // Maps hardware address to BluetoothRouteInfo
final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
@SuppressWarnings("WeakerAccess") /* synthetic access */
BluetoothRouteInfo mSelectedRoute = null;
@@ -127,9 +128,10 @@ class BluetoothRouteProvider {
return;
}
- BluetoothRouteInfo btRouteInfo = mBluetoothRoutes.get(routeId);
+ BluetoothRouteInfo btRouteInfo = findBluetoothRouteWithRouteId(routeId);
+
if (btRouteInfo == null) {
- Slog.w(TAG, "transferTo: unknown route id=" + routeId);
+ Slog.w(TAG, "transferTo: Unknown route. ID=" + routeId);
return;
}
@@ -194,6 +196,18 @@ class BluetoothRouteProvider {
return routes;
}
+ BluetoothRouteInfo findBluetoothRouteWithRouteId(String routeId) {
+ if (routeId == null) {
+ return null;
+ }
+ for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
+ if (TextUtils.equals(btRouteInfo.route.getId(), routeId)) {
+ return btRouteInfo;
+ }
+ }
+ return null;
+ }
+
/**
* Updates the volume for {@link AudioManager#getDevicesForStream(int) devices}.
*
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index 58c2707a1f19..9dae1b44117b 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -85,6 +85,9 @@ final class MediaButtonReceiverHolder {
return null;
}
ComponentName componentName = ComponentName.unflattenFromString(tokens[0]);
+ if (componentName == null) {
+ return null;
+ }
int userId = Integer.parseInt(tokens[1]);
// Guess component type if the OS version is updated from the older version.
int componentType = (tokens.length == 3)
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 93a27f2d17a9..72d296fc5f6b 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -985,6 +985,7 @@ class MediaRouter2ServiceImpl {
if (userRecord == null) {
userRecord = new UserRecord(userId);
mUserRecords.put(userId, userRecord);
+ userRecord.init();
if (userId == mCurrentUserId) {
userRecord.mHandler.sendMessage(
obtainMessage(UserHandler::start, userRecord.mHandler));
@@ -1034,6 +1035,10 @@ class MediaRouter2ServiceImpl {
mHandler = new UserHandler(MediaRouter2ServiceImpl.this, this);
}
+ void init() {
+ mHandler.init();
+ }
+
// TODO: This assumes that only one router exists in a package.
// Do this in Android S or later.
RouterRecord findRouterRecordLocked(String packageName) {
@@ -1141,16 +1146,21 @@ class MediaRouter2ServiceImpl {
private boolean mRunning;
+ // TODO: (In Android S+) Pull out SystemMediaRoute2Provider out of UserHandler.
UserHandler(@NonNull MediaRouter2ServiceImpl service, @NonNull UserRecord userRecord) {
super(Looper.getMainLooper(), null, true);
mServiceRef = new WeakReference<>(service);
mUserRecord = userRecord;
- mSystemProvider = new SystemMediaRoute2Provider(service.mContext, this);
+ mSystemProvider = new SystemMediaRoute2Provider(service.mContext);
mRouteProviders.add(mSystemProvider);
mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this,
this, mUserRecord.mUserId);
}
+ void init() {
+ mSystemProvider.setCallback(this);
+ }
+
private void start() {
if (!mRunning) {
mRunning = true;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 96250411f984..242132c8e5ff 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -2572,6 +2572,9 @@ public class MediaSessionService extends SystemService implements Monitor {
}
} else {
if (mKeyType == KEY_TYPE_VOLUME) {
+ if (isFirstLongPressKeyEvent(keyEvent)) {
+ dispatchVolumeKeyLongPressLocked(mTrackingFirstDownKeyEvent);
+ }
dispatchVolumeKeyLongPressLocked(keyEvent);
} else if (isFirstLongPressKeyEvent(keyEvent)
&& isVoiceKey(keyEvent.getKeyCode())) {
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index d7e724780c94..e01f36513c5c 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -45,6 +45,7 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Slog;
import com.android.internal.R;
@@ -58,8 +59,7 @@ import java.util.Objects;
// TODO: check thread safety. We may need to use lock to protect variables.
class SystemMediaRoute2Provider extends MediaRoute2Provider {
private static final String TAG = "MR2SystemProvider";
- // TODO(b/156996903): Revert it when releasing the framework.
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
@@ -98,12 +98,10 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
}
};
- SystemMediaRoute2Provider(Context context, Callback callback) {
+ SystemMediaRoute2Provider(Context context) {
super(sComponentName);
- setCallback(callback);
mIsSystemRouteProvider = true;
-
mContext = context;
mHandler = new Handler(Looper.getMainLooper());
@@ -143,6 +141,13 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
}
@Override
+ public void setCallback(Callback callback) {
+ super.setCallback(callback);
+ notifyProviderState();
+ notifySessionInfoUpdated();
+ }
+
+ @Override
public void requestCreateSession(long requestId, String packageName, String routeId,
Bundle sessionHints) {
// Assume a router without MODIFY_AUDIO_ROUTING permission can't request with
@@ -354,6 +359,10 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
}
void notifySessionInfoUpdated() {
+ if (mCallback == null) {
+ return;
+ }
+
RoutingSessionInfo sessionInfo;
synchronized (mLock) {
sessionInfo = mSessionInfos.get(0);
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
index 0ec4b39d8960..18da33ce19e0 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
@@ -65,6 +65,7 @@ public class NotificationHistoryDatabase {
private static final int HISTORY_RETENTION_DAYS = 1;
private static final int HISTORY_RETENTION_MS = 24 * 60 * 60 * 1000;
private static final long WRITE_BUFFER_INTERVAL_MS = 1000 * 60 * 20;
+ private static final long INVALID_FILE_TIME_MS = -1;
private static final String ACTION_HISTORY_DELETION =
NotificationHistoryDatabase.class.getSimpleName() + ".CLEANUP";
@@ -130,8 +131,8 @@ public class NotificationHistoryDatabase {
}
// Sort with newest files first
- Arrays.sort(files, (lhs, rhs) -> Long.compare(Long.parseLong(rhs.getName()),
- Long.parseLong(lhs.getName())));
+ Arrays.sort(files, (lhs, rhs) -> Long.compare(safeParseLong(rhs.getName()),
+ safeParseLong(lhs.getName())));
for (File file : files) {
mHistoryFiles.addLast(new AtomicFile(file));
@@ -252,22 +253,19 @@ public class NotificationHistoryDatabase {
for (int i = mHistoryFiles.size() - 1; i >= 0; i--) {
final AtomicFile currentOldestFile = mHistoryFiles.get(i);
- try {
- final long creationTime = Long.parseLong(
- currentOldestFile.getBaseFile().getName());
- if (DEBUG) {
- Slog.d(TAG, "File " + currentOldestFile.getBaseFile().getName()
- + " created on " + creationTime);
- }
- if (creationTime <= retentionBoundary.getTimeInMillis()) {
- deleteFile(currentOldestFile);
- } else {
- // all remaining files are newer than the cut off; schedule jobs to delete
- scheduleDeletion(
- currentOldestFile.getBaseFile(), creationTime, retentionDays);
- }
- } catch (NumberFormatException e) {
+ final long creationTime = safeParseLong(
+ currentOldestFile.getBaseFile().getName());
+ if (DEBUG) {
+ Slog.d(TAG, "File " + currentOldestFile.getBaseFile().getName()
+ + " created on " + creationTime);
+ }
+
+ if (creationTime <= retentionBoundary.getTimeInMillis()) {
deleteFile(currentOldestFile);
+ } else {
+ // all remaining files are newer than the cut off; schedule jobs to delete
+ scheduleDeletion(
+ currentOldestFile.getBaseFile(), creationTime, retentionDays);
}
}
}
@@ -331,6 +329,17 @@ public class NotificationHistoryDatabase {
}
}
+ private static long safeParseLong(String fileName) {
+ // AtomicFile will create copies of the numeric files with ".new" and ".bak"
+ // over the course of its processing. If these files still exist on boot we need to clean
+ // them up
+ try {
+ return Long.parseLong(fileName);
+ } catch (NumberFormatException e) {
+ return INVALID_FILE_TIME_MS;
+ }
+ }
+
private final BroadcastReceiver mFileCleaupReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index afc75572ae4f..b047970183d4 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -90,7 +90,7 @@ public class PreferencesHelper implements RankingConfig {
private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":";
@VisibleForTesting
- static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
+ static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 50000;
private static final int NOTIFICATION_PREFERENCES_PULL_LIMIT = 1000;
private static final int NOTIFICATION_CHANNEL_PULL_LIMIT = 2000;
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index ccda5875d9fa..8a7702efcba8 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -96,6 +96,14 @@ public class AppsFilter {
private final SparseSetArray<Integer> mQueriesViaComponent = new SparseSetArray<>();
/**
+ * Pending full recompute of mQueriesViaComponent. Occurs when a package adds a new set of
+ * protected broadcast. This in turn invalidates all prior additions and require a very
+ * computationally expensive recomputing.
+ * Full recompute is done lazily at the point when we use mQueriesViaComponent to filter apps.
+ */
+ private boolean mQueriesViaComponentRequireRecompute = false;
+
+ /**
* A set of App IDs that are always queryable by any package, regardless of their manifest
* content.
*/
@@ -278,7 +286,7 @@ public class AppsFilter {
private void updateEnabledState(AndroidPackage pkg) {
// TODO(b/135203078): Do not use toAppInfo
- final boolean enabled = mInjector.getCompatibility().isChangeEnabled(
+ final boolean enabled = mInjector.getCompatibility().isChangeEnabledInternal(
PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
if (enabled) {
mDisabledPackages.remove(pkg.getPackageName());
@@ -523,9 +531,8 @@ public class AppsFilter {
return;
}
- if (!newPkg.getProtectedBroadcasts().isEmpty()) {
- mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts());
- recomputeComponentVisibility(existingSettings, newPkg.getPackageName());
+ if (mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts())) {
+ mQueriesViaComponentRequireRecompute = true;
}
final boolean newIsForceQueryable =
@@ -550,7 +557,8 @@ public class AppsFilter {
final AndroidPackage existingPkg = existingSetting.pkg;
// let's evaluate the ability of already added packages to see this new package
if (!newIsForceQueryable) {
- if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) {
+ if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(existingPkg,
+ newPkg, mProtectedBroadcasts)) {
mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId);
}
if (canQueryViaPackage(existingPkg, newPkg)
@@ -560,7 +568,8 @@ public class AppsFilter {
}
// now we'll evaluate our new package's ability to see existing packages
if (!mForceQueryable.contains(existingSetting.appId)) {
- if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) {
+ if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(newPkg,
+ existingPkg, mProtectedBroadcasts)) {
mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId);
}
if (canQueryViaPackage(newPkg, existingPkg)
@@ -646,7 +655,7 @@ public class AppsFilter {
final int appxUidCount = userCount * allSettings.size();
for (int su = 0; su < userCount; su++) {
int subjectUser = allUsers[su].id;
- for (int ou = su; ou < userCount; ou++) {
+ for (int ou = 0; ou < userCount; ou++) {
int otherUser = allUsers[ou].id;
int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId);
if (!mShouldFilterCache.contains(subjectUid)) {
@@ -689,13 +698,11 @@ public class AppsFilter {
return ret;
}
- private void recomputeComponentVisibility(ArrayMap<String, PackageSetting> existingSettings,
- @Nullable String excludePackage) {
+ private void recomputeComponentVisibility(ArrayMap<String, PackageSetting> existingSettings) {
mQueriesViaComponent.clear();
for (int i = existingSettings.size() - 1; i >= 0; i--) {
PackageSetting setting = existingSettings.valueAt(i);
if (setting.pkg == null
- || setting.pkg.getPackageName().equals(excludePackage)
|| mForceQueryable.contains(setting.appId)) {
continue;
}
@@ -704,8 +711,7 @@ public class AppsFilter {
continue;
}
final PackageSetting otherSetting = existingSettings.valueAt(j);
- if (otherSetting.pkg == null
- || otherSetting.pkg.getPackageName().equals(excludePackage)) {
+ if (otherSetting.pkg == null) {
continue;
}
if (canQueryViaComponents(setting.pkg, otherSetting.pkg, mProtectedBroadcasts)) {
@@ -713,6 +719,7 @@ public class AppsFilter {
}
}
}
+ mQueriesViaComponentRequireRecompute = false;
}
/**
@@ -787,9 +794,11 @@ public class AppsFilter {
}
}
- mQueriesViaComponent.remove(setting.appId);
- for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
- mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.appId);
+ if (!mQueriesViaComponentRequireRecompute) {
+ mQueriesViaComponent.remove(setting.appId);
+ for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
+ mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.appId);
+ }
}
mQueriesViaPackage.remove(setting.appId);
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
@@ -808,20 +817,27 @@ public class AppsFilter {
}
}
- if (!setting.pkg.getProtectedBroadcasts().isEmpty()) {
+ if (setting.pkg != null && !setting.pkg.getProtectedBroadcasts().isEmpty()) {
final String removingPackageName = setting.pkg.getPackageName();
- mProtectedBroadcasts.clear();
- mProtectedBroadcasts.addAll(
- collectProtectedBroadcasts(settings, removingPackageName));
- recomputeComponentVisibility(settings, removingPackageName);
+ final Set<String> protectedBroadcasts = mProtectedBroadcasts;
+ mProtectedBroadcasts = collectProtectedBroadcasts(settings, removingPackageName);
+ if (!mProtectedBroadcasts.containsAll(protectedBroadcasts)) {
+ mQueriesViaComponentRequireRecompute = true;
+ }
}
mOverlayReferenceMapper.removePkg(setting.name);
mFeatureConfig.updatePackageState(setting, true /*removed*/);
- if (mShouldFilterCache != null) {
- updateShouldFilterCacheForPackage(
- setting.name, setting, settings, users, settings.size());
+ if (mShouldFilterCache != null && setting.sharedUser != null) {
+ for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
+ PackageSetting siblingSetting = setting.sharedUser.packages.valueAt(i);
+ if (siblingSetting == setting) {
+ continue;
+ }
+ updateShouldFilterCacheForPackage(
+ setting.name, siblingSetting, settings, users, settings.size());
+ }
}
});
mForceQueryable.remove(setting.appId);
@@ -843,8 +859,10 @@ public class AppsFilter {
PackageSetting targetPkgSetting, int userId) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
try {
- if (callingUid < Process.FIRST_APPLICATION_UID
- || UserHandle.getAppId(callingUid) == targetPkgSetting.appId) {
+ int callingAppId = UserHandle.getAppId(callingUid);
+ if (callingAppId < Process.FIRST_APPLICATION_UID
+ || targetPkgSetting.appId < Process.FIRST_APPLICATION_UID
+ || callingAppId == targetPkgSetting.appId) {
return false;
}
if (mShouldFilterCache != null) { // use cache
@@ -869,7 +887,7 @@ public class AppsFilter {
return false;
}
}
- if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(UserHandle.getAppId(callingUid))) {
+ if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(callingAppId)) {
log(callingSetting, targetPkgSetting, "BLOCKED");
}
return !DEBUG_ALLOW_ALL;
@@ -1003,6 +1021,11 @@ public class AppsFilter {
}
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaComponent");
+ if (mQueriesViaComponentRequireRecompute) {
+ mStateProvider.runWithState((settings, users) -> {
+ recomputeComponentVisibility(settings);
+ });
+ }
if (mQueriesViaComponent.contains(callingAppId, targetAppId)) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting, "queries component");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f3bc0561b6ad..dc7ed34fb0be 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2988,7 +2988,7 @@ public class PackageManagerService extends IPackageManager.Stub
t.traceEnd();
t.traceBegin("read user settings");
- mFirstBoot = !mSettings.readLPw(mUserManager.getUsers(false));
+ mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false));
t.traceEnd();
// Clean up orphaned packages for which the code path doesn't exist
@@ -3175,6 +3175,10 @@ public class PackageManagerService extends IPackageManager.Stub
psit.remove();
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; it's data will be wiped");
+
+ // Assume package is truly gone and wipe residual permissions.
+ mPermissionManager.updatePermissions(ps.name, null);
+
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
@@ -3427,7 +3431,7 @@ public class PackageManagerService extends IPackageManager.Stub
// boot, then we need to initialize the default preferred apps across
// all defined users.
if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
- for (UserInfo user : mUserManager.getUsers(true)) {
+ for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
@@ -12144,15 +12148,17 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- // Ensure the package is signed with at least the minimum signature scheme version
- // required for its target SDK.
- int minSignatureSchemeVersion =
- ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
- pkg.getTargetSdkVersion());
- if (pkg.getSigningDetails().signatureSchemeVersion < minSignatureSchemeVersion) {
- throw new PackageManagerException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
- "No signature found in package of version " + minSignatureSchemeVersion
- + " or newer for package " + pkg.getPackageName());
+ // If the package is not on a system partition ensure it is signed with at least the
+ // minimum signature scheme version required for its target SDK.
+ if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ int minSignatureSchemeVersion =
+ ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
+ pkg.getTargetSdkVersion());
+ if (pkg.getSigningDetails().signatureSchemeVersion < minSignatureSchemeVersion) {
+ throw new PackageManagerException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+ "No signature found in package of version " + minSignatureSchemeVersion
+ + " or newer for package " + pkg.getPackageName());
+ }
}
}
}
@@ -22137,7 +22143,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
for (String packageName : apkList) {
setSystemAppHiddenUntilInstalled(packageName, true);
- for (UserInfo user : mUserManager.getUsers(false)) {
+ for (UserInfo user : mInjector.getUserManagerInternal().getUsers(false)) {
setSystemAppInstallState(packageName, false, user.id);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 1fce07b0cbf1..03f4708c09c4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -595,8 +595,8 @@ public class PackageManagerServiceUtils {
/** Returns true to force apk verification if the package is considered privileged. */
static boolean isApkVerificationForced(@Nullable PackageSetting ps) {
- return ps != null && ps.isPrivileged() && (
- isApkVerityEnabled() || isLegacyApkVerityEnabled());
+ // TODO(b/154310064): re-enable.
+ return false;
}
/**
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 2a6997cba4bb..27924a68ff48 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -751,13 +751,19 @@ public class UserManagerService extends IUserManager.Stub {
}
public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
- return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */ true);
+ return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */
+ true);
}
@Override
public @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
boolean excludePreCreated) {
checkManageOrCreateUsersPermission("query users");
+ return getUsersInternal(excludePartial, excludeDying, excludePreCreated);
+ }
+
+ private @NonNull List<UserInfo> getUsersInternal(boolean excludePartial, boolean excludeDying,
+ boolean excludePreCreated) {
synchronized (mUsersLock) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
final int userSize = mUsers.size();
@@ -3291,11 +3297,13 @@ public class UserManagerService extends IUserManager.Stub {
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
t.traceBegin("createUser-" + flags);
final long sessionId = logUserCreateJourneyBegin(nextProbableUserId, userType, flags);
+ UserInfo newUser = null;
try {
- return createUserInternalUncheckedNoTracing(name, userType, flags, parentId,
- preCreate, disallowedPackages, t);
+ newUser = createUserInternalUncheckedNoTracing(name, userType, flags, parentId,
+ preCreate, disallowedPackages, t);
+ return newUser;
} finally {
- logUserCreateJourneyFinish(sessionId, nextProbableUserId);
+ logUserCreateJourneyFinish(sessionId, nextProbableUserId, newUser != null);
t.traceEnd();
}
}
@@ -3314,10 +3322,11 @@ public class UserManagerService extends IUserManager.Stub {
return sessionId;
}
- private void logUserCreateJourneyFinish(long sessionId, @UserIdInt int userId) {
+ private void logUserCreateJourneyFinish(long sessionId, @UserIdInt int userId, boolean finish) {
FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId,
FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER,
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH);
+ finish ? FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH
+ : FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE);
}
private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name,
@@ -5042,6 +5051,12 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
+ public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
+ return UserManagerService.this.getUsersInternal(/*excludePartial= */ true,
+ excludeDying, /* excludePreCreated= */ true);
+ }
+
+ @Override
public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
int state;
synchronized (mUserStates) {
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index 8b6e9a46ca91..2e5c0f460c7a 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -510,7 +510,8 @@ public class BatterySaverController implements BatterySaverPolicyListener {
if (getPowerSaveModeChangedListenerPackage().isPresent()) {
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
.setPackage(getPowerSaveModeChangedListenerPackage().get())
- .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+ | Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
index 9d6a64701e85..b00540fd2a52 100644
--- a/services/core/java/com/android/server/storage/AppFuseBridge.java
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -56,6 +56,15 @@ public class AppFuseBridge implements Runnable {
public ParcelFileDescriptor addBridge(MountScope mountScope)
throws FuseUnavailableMountException, NativeDaemonConnectorException {
+ /*
+ ** Dead Lock between Java lock (AppFuseBridge.java) and Native lock (FuseBridgeLoop.cc)
+ **
+ ** (Thread A) Got Java lock (addBrdige) -> Try to get Native lock (native_add_brdige)
+ ** (Thread B) Got Native lock (FuseBrdigeLoop.start) -> Try to get Java lock (onClosed)
+ **
+ ** Guarantee the lock order (native lock -> java lock) when adding Bridge.
+ */
+ native_lock();
try {
synchronized (this) {
Preconditions.checkArgument(mScopes.indexOfKey(mountScope.mountId) < 0);
@@ -73,6 +82,7 @@ public class AppFuseBridge implements Runnable {
return result;
}
} finally {
+ native_unlock();
IoUtils.closeQuietly(mountScope);
}
}
@@ -159,4 +169,6 @@ public class AppFuseBridge implements Runnable {
private native void native_delete(long loop);
private native void native_start_loop(long loop);
private native int native_add_bridge(long loop, int mountId, int deviceId);
+ private native void native_lock();
+ private native void native_unlock();
}
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 0fd77b9c03dd..37df5481d3c4 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -27,7 +27,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.os.Handler;
import android.os.IVold;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -238,7 +237,7 @@ public final class StorageSessionController {
*
* Does nothing if {@link #shouldHandle} is {@code false}
**/
- public void onReset(IVold vold, Handler handler) {
+ public void onReset(IVold vold, Runnable resetHandlerRunnable) {
if (!shouldHandle(null)) {
return;
}
@@ -280,7 +279,7 @@ public final class StorageSessionController {
connection.close();
}
- handler.removeCallbacksAndMessages(null);
+ resetHandlerRunnable.run();
synchronized (mLock) {
mConnections.clear();
mIsResetting = false;
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 94a250236200..ed5706752cb2 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -62,7 +62,7 @@ import java.util.concurrent.TimeoutException;
public final class StorageUserConnection {
private static final String TAG = "StorageUserConnection";
- public static final int REMOTE_TIMEOUT_SECONDS = 5;
+ public static final int REMOTE_TIMEOUT_SECONDS = 20;
private final Object mLock = new Object();
private final Context mContext;
@@ -202,6 +202,7 @@ public final class StorageUserConnection {
try {
if (!latch.await(REMOTE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
// TODO(b/140025078): Call ActivityManager ANR API?
+ Slog.wtf(TAG, "Failed to bind to the ExternalStorageService for user " + mUserId);
throw new TimeoutException("Latch wait for " + reason + " elapsed");
}
} catch (InterruptedException e) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 304860c2588f..319fd18faca5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2208,7 +2208,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
boolean isResizeable() {
- return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
+ return mAtmService.mForceResizableActivities
+ || ActivityInfo.isResizeableMode(info.resizeMode)
+ || info.supportsPictureInPicture();
}
/** @return whether this activity is non-resizeable or forced to be resizeable */
@@ -4341,9 +4343,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* screenshot.
*/
boolean shouldUseAppThemeSnapshot() {
- return mDisablePreviewScreenshots || forAllWindows(w -> {
- return mWmService.isSecureLocked(w);
- }, true /* topToBottom */);
+ return mDisablePreviewScreenshots || forAllWindows(WindowState::isSecureLocked,
+ true /* topToBottom */);
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 1f9e8609c2ad..407b9fcbca74 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -73,6 +73,7 @@ import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_
import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
@@ -1809,7 +1810,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
for (int i = mStoppingActivities.size() - 1; i >= 0; --i) {
final ActivityRecord s = mStoppingActivities.get(i);
final boolean animating = s.isAnimating(TRANSITION | PARENTS,
- ANIMATION_TYPE_APP_TRANSITION);
+ ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS);
if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + s.nowVisible
+ " animating=" + animating + " finishing=" + s.finishing);
if (!animating || mService.mShuttingDown) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 6dd1ea934497..cbd2b3358239 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3824,7 +3824,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
userId = activity.mUserId;
}
- return !DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId);
+ return DevicePolicyCache.getInstance().isScreenCaptureAllowed(userId, false);
}
@Override
@@ -5413,7 +5413,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final boolean hideDialogsSet = Settings.Global.getInt(mContext.getContentResolver(),
HIDE_ERROR_DIALOGS, 0) != 0;
mShowDialogs = inputMethodExists
- && ActivityTaskManager.currentUiModeSupportsErrorDialogs(mContext)
+ && ActivityTaskManager.currentUiModeSupportsErrorDialogs(config)
&& !hideDialogsSet;
}
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index efcb558fef66..6305fda4924c 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -16,17 +16,19 @@
package com.android.server.wm;
-import android.view.SurfaceControl;
+import android.util.ArrayMap;
+import android.util.ArraySet;
-import java.util.HashMap;
+import java.util.Set;
/**
- * Utility class for collecting and merging transactions from various sources asynchronously.
+ * Utility class for collecting WindowContainers that will merge transactions.
* For example to use to synchronously resize all the children of a window container
* 1. Open a new sync set, and pass the listener that will be invoked
* int id startSyncSet(TransactionReadyListener)
* the returned ID will be eventually passed to the TransactionReadyListener in combination
- * with the prepared transaction. You also use it to refer to the operation in future steps.
+ * with a set of WindowContainers that are ready, meaning onTransactionReady was called for
+ * those WindowContainers. You also use it to refer to the operation in future steps.
* 2. Ask each child to participate:
* addToSyncSet(int id, WindowContainer wc)
* if the child thinks it will be affected by a configuration change (a.k.a. has a visible
@@ -38,35 +40,37 @@ import java.util.HashMap;
* setReady(int id)
* 5. If there were no sub windows anywhere in the hierarchy to wait on, then
* transactionReady is immediately invoked, otherwise all the windows are poked
- * to redraw and to deliver a buffer to WMS#finishDrawing.
- * Once all this drawing is complete the combined transaction of all the buffers
- * and pending transaction hierarchy changes will be delivered to the TransactionReadyListener
+ * to redraw and to deliver a buffer to {@link WindowState#finishDrawing}.
+ * Once all this drawing is complete the WindowContainer that's ready will be added to the
+ * set of ready WindowContainers. When the final onTransactionReady is called, it will merge
+ * the transactions of the all the WindowContainers and will be delivered to the
+ * TransactionReadyListener
*/
class BLASTSyncEngine {
private static final String TAG = "BLASTSyncEngine";
interface TransactionReadyListener {
- void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction);
+ void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady);
};
// Holds state associated with a single synchronous set of operations.
class SyncState implements TransactionReadyListener {
int mSyncId;
- SurfaceControl.Transaction mMergedTransaction;
int mRemainingTransactions;
TransactionReadyListener mListener;
boolean mReady = false;
+ Set<WindowContainer> mWindowContainersReady = new ArraySet<>();
private void tryFinish() {
if (mRemainingTransactions == 0 && mReady) {
- mListener.onTransactionReady(mSyncId, mMergedTransaction);
+ mListener.onTransactionReady(mSyncId, mWindowContainersReady);
mPendingSyncs.remove(mSyncId);
}
}
- public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
+ public void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady) {
mRemainingTransactions--;
- mMergedTransaction.merge(mergedTransaction);
+ mWindowContainersReady.addAll(windowContainersReady);
tryFinish();
}
@@ -86,14 +90,13 @@ class BLASTSyncEngine {
SyncState(TransactionReadyListener l, int id) {
mListener = l;
mSyncId = id;
- mMergedTransaction = new SurfaceControl.Transaction();
mRemainingTransactions = 0;
}
};
- int mNextSyncId = 0;
+ private int mNextSyncId = 0;
- final HashMap<Integer, SyncState> mPendingSyncs = new HashMap();
+ private final ArrayMap<Integer, SyncState> mPendingSyncs = new ArrayMap<>();
BLASTSyncEngine() {
}
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index b2fab9ae98c5..8260cb31acda 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -290,7 +290,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
mDimmer.resetDimStates();
}
- if (mDimmer.updateDims(getSyncTransaction(), mTmpDimBoundsRect)) {
+ if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
scheduleAnimation();
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c24c1e466133..5e3688029bec 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3782,7 +3782,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
boolean hasSecureWindowOnScreen() {
- final WindowState win = getWindow(w -> w.isOnScreen() && mWmService.isSecureLocked(w));
+ final WindowState win = getWindow(w -> w.isOnScreen() && w.isSecureLocked());
return win != null;
}
@@ -5664,10 +5664,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* Return {@code true} if there is an ongoing animation to the "Recents" activity and this
* activity as a fixed orientation so shouldn't be rotated.
*/
- boolean isFixedOrientationRecentsAnimating() {
+ boolean isTopFixedOrientationRecentsAnimating() {
return mAnimatingRecents != null
&& mAnimatingRecents.getRequestedConfigurationOrientation()
- != ORIENTATION_UNDEFINED;
+ != ORIENTATION_UNDEFINED && !hasTopFixedRotationLaunchingApp();
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 3c4a9ad08199..8cfe1cd5e98f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1833,10 +1833,11 @@ public class DisplayPolicy {
if (navBarPosition == NAV_BAR_BOTTOM) {
// It's a system nav bar or a portrait screen; nav bar goes on bottom.
- final int top = cutoutSafeUnrestricted.bottom
- - getNavigationBarHeight(rotation, uiMode);
final int topNavBar = cutoutSafeUnrestricted.bottom
- getNavigationBarFrameHeight(rotation, uiMode);
+ final int top = mNavButtonForcedVisible
+ ? topNavBar
+ : cutoutSafeUnrestricted.bottom - getNavigationBarHeight(rotation, uiMode);
navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
if (transientNavBarShowing) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index f093fd34bcc0..37ecee8e3db3 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -432,7 +432,7 @@ public class DisplayRotation {
}
if (mDisplayContent.mFixedRotationTransitionListener
- .isFixedOrientationRecentsAnimating()) {
+ .isTopFixedOrientationRecentsAnimating()) {
// During the recents animation, the closing app might still be considered on top.
// In order to ignore its requested orientation to avoid a sensor led rotation (e.g
// user rotating the device while the recents animation is running), we ignore
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3d7873ad2f7c..56c46d2b6422 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -111,15 +111,20 @@ class InsetsPolicy {
abortTransient();
}
mFocusedWin = focusedWin;
- mStateController.onBarControlTargetChanged(getStatusControlTarget(focusedWin),
- getFakeStatusControlTarget(focusedWin),
- getNavControlTarget(focusedWin),
- getFakeNavControlTarget(focusedWin));
+ boolean forceShowsSystemBarsForWindowingMode = forceShowsSystemBarsForWindowingMode();
+ InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin,
+ forceShowsSystemBarsForWindowingMode);
+ InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin,
+ forceShowsSystemBarsForWindowingMode);
+ mStateController.onBarControlTargetChanged(statusControlTarget,
+ getFakeControlTarget(focusedWin, statusControlTarget),
+ navControlTarget,
+ getFakeControlTarget(focusedWin, navControlTarget));
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
return;
}
- mStatusBar.updateVisibility(getStatusControlTarget(focusedWin), ITYPE_STATUS_BAR);
- mNavBar.updateVisibility(getNavControlTarget(focusedWin), ITYPE_NAVIGATION_BAR);
+ mStatusBar.updateVisibility(statusControlTarget, ITYPE_STATUS_BAR);
+ mNavBar.updateVisibility(navControlTarget, ITYPE_NAVIGATION_BAR);
mPolicy.updateHideNavInputEventReceiver();
}
@@ -237,16 +242,13 @@ class InsetsPolicy {
updateBarControlTarget(mFocusedWin);
}
- private @Nullable InsetsControlTarget getFakeStatusControlTarget(
- @Nullable WindowState focused) {
- return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null;
+ private @Nullable InsetsControlTarget getFakeControlTarget(@Nullable WindowState focused,
+ InsetsControlTarget realControlTarget) {
+ return realControlTarget == mDummyControlTarget ? focused : null;
}
- private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) {
- return getNavControlTarget(focused) == mDummyControlTarget ? focused : null;
- }
-
- private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) {
+ private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin,
+ boolean forceShowsSystemBarsForWindowingMode) {
if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
return mDummyControlTarget;
}
@@ -254,7 +256,7 @@ class InsetsPolicy {
// Notification shade has control anyways, no reason to force anything.
return focusedWin;
}
- if (forceShowsSystemBarsForWindowingMode()) {
+ if (forceShowsSystemBarsForWindowingMode) {
// Status bar is forcibly shown for the windowing mode which is a steady state.
// We don't want the client to control the status bar, and we will dispatch the real
// visibility of status bar to the client.
@@ -274,7 +276,8 @@ class InsetsPolicy {
return focusedWin;
}
- private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) {
+ private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin,
+ boolean forceShowsSystemBarsForWindowingMode) {
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
return mDummyControlTarget;
}
@@ -282,7 +285,7 @@ class InsetsPolicy {
// Notification shade has control anyways, no reason to force anything.
return focusedWin;
}
- if (forceShowsSystemBarsForWindowingMode()) {
+ if (forceShowsSystemBarsForWindowingMode) {
// Navigation bar is forcibly shown for the windowing mode which is a steady state.
// We don't want the client to control the navigation bar, and we will dispatch the real
// visibility of navigation bar to the client.
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index bf9a78489167..e80d5937eb1f 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -254,8 +254,9 @@ class InsetsStateController {
void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
boolean changed = false;
- for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
- final InsetsSource source = state.sourceAt(i);
+ for (int i = 0; i < InsetsState.SIZE; i++) {
+ final InsetsSource source = state.peekSource(i);
+ if (source == null) continue;
final InsetsSourceProvider provider = mProviders.get(source.getType());
if (provider == null) {
continue;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 583663c5455f..45a36e562aac 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -662,10 +662,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- void setSecureSurfaceState(int userId, boolean disabled) {
+ void setSecureSurfaceState(int userId) {
forAllWindows((w) -> {
if (w.mHasSurface && userId == w.mShowUserId) {
- w.mWinAnimator.setSecureLocked(disabled);
+ w.mWinAnimator.setSecureLocked(w.isSecureLocked());
}
}, true /* traverseTopToBottom */);
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 5633b6be87b9..837f1b523b68 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -239,9 +239,6 @@ class SurfaceAnimationRunner {
}
private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
- if (a.mAnimSpec.needsEarlyWakeup()) {
- t.setEarlyWakeup();
- }
a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6670dbfea282..fec484935d68 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -939,14 +939,15 @@ class Task extends WindowContainer<WindowContainer> {
/** Sets the original intent, _without_ updating the calling uid or package. */
private void setIntent(Intent _intent, ActivityInfo info) {
+ final boolean isLeaf = isLeafTask();
if (intent == null) {
mNeverRelinquishIdentity =
(info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
- } else if (mNeverRelinquishIdentity) {
+ } else if (mNeverRelinquishIdentity && isLeaf) {
return;
}
- affinity = isLeafTask() ? info.taskAffinity : null;
+ affinity = isLeaf ? info.taskAffinity : null;
if (intent == null) {
// If this task already has an intent associated with it, don't set the root
// affinity -- we don't want it changing after initially set, but the initially
@@ -3506,7 +3507,7 @@ class Task extends WindowContainer<WindowContainer> {
updateShadowsRadius(isFocused(), getSyncTransaction());
- if (mDimmer.updateDims(getSyncTransaction(), mTmpDimBoundsRect)) {
+ if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
scheduleAnimation();
}
}
@@ -3587,6 +3588,7 @@ class Task extends WindowContainer<WindowContainer> {
final Task top = getTopMostTask();
info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
info.topActivityType = top.getActivityType();
+ info.isResizeable = isResizeable();
ActivityRecord rootActivity = top.getRootActivity();
if (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) {
@@ -3684,20 +3686,6 @@ class Task extends WindowContainer<WindowContainer> {
final int otherWindowingMode = other.getWindowingMode();
if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
- // In this case the home stack isn't resizeable even though we are in split-screen
- // mode. We still want the primary splitscreen stack to be visible as there will be
- // a slight hint of it in the status bar area above the non-resizeable home
- // activity. In addition, if the fullscreen assistant is over primary splitscreen
- // stack, the stack should still be visible in the background as long as the recents
- // animation is running.
- final int activityType = other.getActivityType();
- if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- if (activityType == ACTIVITY_TYPE_HOME
- || (activityType == ACTIVITY_TYPE_ASSISTANT
- && mWmService.getRecentsAnimationController() != null)) {
- break;
- }
- }
if (other.isTranslucent(starting)) {
// Can be visible behind a translucent fullscreen stack.
gotTranslucentFullscreen = true;
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 07e309e1126a..46761dc81117 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -571,14 +571,16 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
// Apps and their containers are not allowed to specify an orientation while using
// root tasks...except for the home stack if it is not resizable and currently
// visible (top of) its root task.
- if (mRootHomeTask != null && mRootHomeTask.isVisible()) {
- final Task topMost = mRootHomeTask.getTopMostTask();
- final boolean resizable = topMost != null && topMost.isResizeable();
- if (!(resizable && mRootHomeTask.matchParentBounds())) {
- final int orientation = mRootHomeTask.getOrientation();
- if (orientation != SCREEN_ORIENTATION_UNSET) {
- return orientation;
- }
+ if (mRootHomeTask != null && mRootHomeTask.isVisible()
+ && !mRootHomeTask.isResizeable()) {
+ // Manually nest one-level because because getOrientation() checks fillsParent()
+ // which checks that requestedOverrideBounds() is empty. However, in this case,
+ // it is not empty because it's been overridden to maintain the fullscreen size
+ // within a smaller split-root.
+ final Task topHomeTask = mRootHomeTask.getTopMostTask();
+ final int orientation = topHomeTask.getOrientation();
+ if (orientation != SCREEN_ORIENTATION_UNSET) {
+ return orientation;
}
}
return SCREEN_ORIENTATION_UNSPECIFIED;
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 1da1d116b938..574f37b87443 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -455,7 +455,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
task.fillTaskInfo(mTmpTaskInfo);
boolean changed = lastInfo == null
|| mTmpTaskInfo.topActivityType != lastInfo.topActivityType
- || mTmpTaskInfo.isResizable() != lastInfo.isResizable()
+ || mTmpTaskInfo.isResizeable != lastInfo.isResizeable
|| mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams
|| !TaskDescription.equals(mTmpTaskInfo.taskDescription, lastInfo.taskDescription);
if (!changed) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 1a2672bd0132..51cf858715b4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -28,6 +28,7 @@ import android.app.ActivityManager.TaskSnapshot;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
+import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.RecordingCanvas;
@@ -37,8 +38,11 @@ import android.os.Environment;
import android.os.Handler;
import android.util.ArraySet;
import android.util.Slog;
+import android.view.InsetsSource;
+import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.ThreadedRenderer;
+import android.view.WindowInsets;
import android.view.WindowManager.LayoutParams;
import com.android.internal.annotations.VisibleForTesting;
@@ -475,9 +479,12 @@ class TaskSnapshotController {
final int color = ColorUtils.setAlphaComponent(
task.getTaskDescription().getBackgroundColor(), 255);
final LayoutParams attrs = mainWindow.getAttrs();
+ final InsetsPolicy insetsPolicy = mainWindow.getDisplayContent().getInsetsPolicy();
+ final InsetsState insetsState = insetsPolicy.getInsetsForDispatch(mainWindow);
+ final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrameLw(), insetsState);
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription(),
- mHighResTaskSnapshotScale, mainWindow.getRequestedInsetsState());
+ mHighResTaskSnapshotScale, insetsState);
final int taskWidth = task.getBounds().width();
final int taskHeight = task.getBounds().height();
final int width = (int) (taskWidth * mHighResTaskSnapshotScale);
@@ -488,7 +495,7 @@ class TaskSnapshotController {
node.setClipToBounds(false);
final RecordingCanvas c = node.start(width, height);
c.drawColor(color);
- decorPainter.setInsets(mainWindow.getContentInsets(), mainWindow.getStableInsets());
+ decorPainter.setInsets(systemBarInsets);
decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
node.end(c);
final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
@@ -593,6 +600,13 @@ class TaskSnapshotController {
return 0;
}
+ static Rect getSystemBarInsets(Rect frame, InsetsState state) {
+ return state.calculateInsets(frame, null /* ignoringVisibilityState */,
+ false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
+ null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacySystemUiFlags */,
+ null /* typeSideMap */).getInsets(WindowInsets.Type.systemBars()).toRect();
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "mHighResTaskSnapshotScale=" + mHighResTaskSnapshotScale);
mCache.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index e26f1e1fe06f..f1f576220a9a 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -39,10 +39,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
-import static com.android.internal.policy.DecorView.getColorViewLeftInset;
-import static com.android.internal.policy.DecorView.getColorViewTopInset;
import static com.android.internal.policy.DecorView.getNavigationBarRect;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -131,9 +130,8 @@ class TaskSnapshotSurface implements StartingSurface {
private final IWindowSession mSession;
private final WindowManagerService mService;
private final Rect mTaskBounds;
- private final Rect mStableInsets = new Rect();
- private final Rect mContentInsets = new Rect();
private final Rect mFrame = new Rect();
+ private final Rect mSystemBarInsets = new Rect();
private TaskSnapshot mSnapshot;
private final RectF mTmpSnapshotSize = new RectF();
private final RectF mTmpDstFrame = new RectF();
@@ -174,6 +172,7 @@ class TaskSnapshotSurface implements StartingSurface {
final int windowFlags;
final int windowPrivateFlags;
final int currentOrientation;
+ final InsetsState insetsState;
synchronized (service.mGlobalLock) {
final WindowState mainWindow = activity.findMainWindow();
final Task task = activity.getTask();
@@ -241,6 +240,10 @@ class TaskSnapshotSurface implements StartingSurface {
taskBounds = new Rect();
task.getBounds(taskBounds);
currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
+
+ final InsetsPolicy insetsPolicy = topFullscreenOpaqueWindow.getDisplayContent()
+ .getInsetsPolicy();
+ insetsState = insetsPolicy.getInsetsForDispatch(topFullscreenOpaqueWindow);
}
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
@@ -255,8 +258,7 @@ class TaskSnapshotSurface implements StartingSurface {
}
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
- windowFlags, windowPrivateFlags, taskBounds,
- currentOrientation, topFullscreenOpaqueWindow.getRequestedInsetsState());
+ windowFlags, windowPrivateFlags, taskBounds, currentOrientation, insetsState);
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
@@ -266,7 +268,9 @@ class TaskSnapshotSurface implements StartingSurface {
} catch (RemoteException e) {
// Local call.
}
- snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
+
+ final Rect systemBarInsets = getSystemBarInsets(tmpFrame, insetsState);
+ snapshotSurface.setFrames(tmpFrame, systemBarInsets);
snapshotSurface.drawSnapshot();
return snapshotSurface;
}
@@ -315,13 +319,12 @@ class TaskSnapshotSurface implements StartingSurface {
}
@VisibleForTesting
- void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
+ void setFrames(Rect frame, Rect systemBarInsets) {
mFrame.set(frame);
- mContentInsets.set(contentInsets);
- mStableInsets.set(stableInsets);
+ mSystemBarInsets.set(systemBarInsets);
mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
|| mFrame.height() != mSnapshot.getSnapshot().getHeight());
- mSystemBarBackgroundPainter.setInsets(contentInsets, stableInsets);
+ mSystemBarBackgroundPainter.setInsets(systemBarInsets);
}
private void drawSnapshot() {
@@ -453,9 +456,7 @@ class TaskSnapshotSurface implements StartingSurface {
);
// However, we also need to make space for the navigation bar on the left side.
- final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
- mContentInsets.left);
- frame.offset(colorViewLeftInset, 0);
+ frame.offset(mSystemBarInsets.left, 0);
return frame;
}
@@ -540,8 +541,6 @@ class TaskSnapshotSurface implements StartingSurface {
*/
static class SystemBarBackgroundPainter {
- private final Rect mContentInsets = new Rect();
- private final Rect mStableInsets = new Rect();
private final Paint mStatusBarPaint = new Paint();
private final Paint mNavigationBarPaint = new Paint();
private final int mStatusBarColor;
@@ -551,6 +550,7 @@ class TaskSnapshotSurface implements StartingSurface {
private final int mSysUiVis;
private final float mScale;
private final InsetsState mInsetsState;
+ private final Rect mSystemBarInsets = new Rect();
SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int sysUiVis,
TaskDescription taskDescription, float scale, InsetsState insetsState) {
@@ -576,9 +576,8 @@ class TaskSnapshotSurface implements StartingSurface {
mInsetsState = insetsState;
}
- void setInsets(Rect contentInsets, Rect stableInsets) {
- mContentInsets.set(contentInsets);
- mStableInsets.set(stableInsets);
+ void setInsets(Rect systemBarInsets) {
+ mSystemBarInsets.set(systemBarInsets);
}
int getStatusBarColorViewHeight() {
@@ -589,7 +588,7 @@ class TaskSnapshotSurface implements StartingSurface {
mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)
: STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
- return (int) (getColorViewTopInset(mStableInsets.top, mContentInsets.top) * mScale);
+ return (int) (mSystemBarInsets.top * mScale);
} else {
return 0;
}
@@ -615,8 +614,7 @@ class TaskSnapshotSurface implements StartingSurface {
int statusBarHeight) {
if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
&& (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
- final int rightInset = (int) (DecorView.getColorViewRightInset(mStableInsets.right,
- mContentInsets.right) * mScale);
+ final int rightInset = (int) (mSystemBarInsets.right * mScale);
final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
}
@@ -625,8 +623,8 @@ class TaskSnapshotSurface implements StartingSurface {
@VisibleForTesting
void drawNavigationBarBackground(Canvas c) {
final Rect navigationBarRect = new Rect();
- getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
- navigationBarRect, mScale);
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect,
+ mScale);
final boolean visible = isNavigationBarColorViewVisible();
if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
c.drawRect(navigationBarRect, mNavigationBarPaint);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 92a9e30c2f0a..9d0bac9dd290 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -17,6 +17,10 @@
package com.android.server.wm;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
@@ -52,6 +56,9 @@ public class WindowAnimator {
/** Is any window animating? */
private boolean mLastRootAnimating;
+ /** True if we are running any animations that require expensive composition. */
+ private boolean mRunningExpensiveAnimations;
+
final Choreographer.FrameCallback mAnimationFrameCallback;
/** Time of current animation step. Reset on each iteration */
@@ -165,12 +172,8 @@ public class WindowAnimator {
mService.mWatermark.drawIfNeeded();
}
- SurfaceControl.mergeToGlobalTransaction(mTransaction);
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
- } finally {
- mService.closeSurfaceTransaction("WindowAnimator");
- ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate");
}
final boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
@@ -179,21 +182,36 @@ public class WindowAnimator {
mService.mWindowPlacerLocked.requestTraversal();
}
- final boolean rootAnimating = mService.mRoot.isAnimating(TRANSITION | CHILDREN);
+ final boolean rootAnimating = mService.mRoot.isAnimating(TRANSITION | CHILDREN /* flags */,
+ ANIMATION_TYPE_ALL /* typesToCheck */);
if (rootAnimating && !mLastRootAnimating) {
- // Usually app transitions but quite a load onto the system already (with all the things
- // happening in app), so pause task snapshot persisting to not increase the load.
- mService.mTaskSnapshotController.setPersisterPaused(true);
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
if (!rootAnimating && mLastRootAnimating) {
mService.mWindowPlacerLocked.requestTraversal();
- mService.mTaskSnapshotController.setPersisterPaused(false);
Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
-
mLastRootAnimating = rootAnimating;
+ final boolean runningExpensiveAnimations =
+ mService.mRoot.isAnimating(TRANSITION | CHILDREN /* flags */,
+ ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_SCREEN_ROTATION
+ | ANIMATION_TYPE_RECENTS /* typesToCheck */);
+ if (runningExpensiveAnimations && !mRunningExpensiveAnimations) {
+ // Usually app transitions put quite a load onto the system already (with all the things
+ // happening in app), so pause task snapshot persisting to not increase the load.
+ mService.mTaskSnapshotController.setPersisterPaused(true);
+ mTransaction.setEarlyWakeupStart();
+ } else if (!runningExpensiveAnimations && mRunningExpensiveAnimations) {
+ mService.mTaskSnapshotController.setPersisterPaused(false);
+ mTransaction.setEarlyWakeupEnd();
+ }
+ mRunningExpensiveAnimations = runningExpensiveAnimations;
+
+ SurfaceControl.mergeToGlobalTransaction(mTransaction);
+ mService.closeSurfaceTransaction("WindowAnimator");
+ ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate");
+
if (mRemoveReplacedWindows) {
mService.mRoot.removeReplacedWindows();
mRemoveReplacedWindows = false;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 6406f0ae51a6..3a1619ba11a1 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -93,6 +93,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
+import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -179,6 +180,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* Applied as part of the animation pass in "prepareSurfaces".
*/
protected final SurfaceAnimator mSurfaceAnimator;
+ private boolean mAnyParentAnimating;
+
final SurfaceFreezer mSurfaceFreezer;
protected final WindowManagerService mWmService;
@@ -1032,7 +1035,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* @return Whether this child is on top of the window hierarchy.
*/
boolean isOnTop() {
- return getParent().getTopChild() == this && getParent().isOnTop();
+ final WindowContainer parent = getParent();
+ return parent != null && parent.getTopChild() == this && parent.isOnTop();
}
/** Returns the top child container. */
@@ -2459,21 +2463,16 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
*/
@Nullable
WindowContainer getAnimatingContainer(int flags, int typesToCheck) {
- int animationType = mSurfaceAnimator.getAnimationType();
- if (mSurfaceAnimator.isAnimating() && (animationType & typesToCheck) > 0) {
- return this;
- }
- if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
+ if (isSelfAnimating(flags, typesToCheck)) {
return this;
}
if ((flags & PARENTS) != 0) {
- final WindowContainer parent = getParent();
- if (parent != null) {
- final WindowContainer wc = parent.getAnimatingContainer(
- flags & ~CHILDREN, typesToCheck);
- if (wc != null) {
- return wc;
+ WindowContainer parent = getParent();
+ while (parent != null) {
+ if (parent.isSelfAnimating(flags, typesToCheck)) {
+ return parent;
}
+ parent = parent.getParent();
}
}
if ((flags & CHILDREN) != 0) {
@@ -2489,6 +2488,21 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
/**
+ * Internal method only to be used during {@link #getAnimatingContainer(int, int)}.DO NOT CALL
+ * FROM OUTSIDE.
+ */
+ protected boolean isSelfAnimating(int flags, int typesToCheck) {
+ if (mSurfaceAnimator.isAnimating()
+ && (mSurfaceAnimator.getAnimationType() & typesToCheck) > 0) {
+ return true;
+ }
+ if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
* @deprecated Use {@link #getAnimatingContainer(int, int)} instead.
*/
@Nullable
@@ -2672,11 +2686,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
@Override
- public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
- mergedTransaction.merge(mBLASTSyncTransaction);
- mUsingBLASTSyncTransaction = false;
+ public void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady) {
+ if (mWaitingListener == null) {
+ return;
+ }
- mWaitingListener.onTransactionReady(mWaitingSyncId, mergedTransaction);
+ windowContainersReady.add(this);
+ mWaitingListener.onTransactionReady(mWaitingSyncId, windowContainersReady);
mWaitingListener = null;
mWaitingSyncId = -1;
@@ -2727,4 +2743,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
boolean useBLASTSync() {
return mUsingBLASTSyncTransaction;
}
+
+ void mergeBlastSyncTransaction(Transaction t) {
+ t.merge(mBLASTSyncTransaction);
+ mUsingBLASTSyncTransaction = false;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 10d07573f8c6..27864393d23e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -139,7 +139,6 @@ import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.app.IAssistDataReceiver;
import android.app.WindowConfiguration;
-import android.app.admin.DevicePolicyCache;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -369,7 +368,8 @@ public class WindowManagerService extends IWindowManager.Stub
static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
// Poll interval in milliseconds for watching boot animation finished.
- private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
+ // TODO(b/159045990) Migrate to SystemService.waitForState with dedicated thread.
+ private static final int BOOT_ANIMATION_POLL_INTERVAL = 50;
// The name of the boot animation service in init.rc.
private static final String BOOT_ANIMATION_SERVICE = "bootanim";
@@ -1881,16 +1881,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- boolean isSecureLocked(WindowState w) {
- if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
- return true;
- }
- if (DevicePolicyCache.getInstance().getScreenCaptureDisabled(w.mShowUserId)) {
- return true;
- }
- return false;
- }
-
/**
* Set whether screen capture is disabled for all windows of a specific user from
* the device policy cache.
@@ -1904,8 +1894,7 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized (mGlobalLock) {
// Update secure surface for all windows belonging to this user.
- mRoot.setSecureSurfaceState(userId,
- DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId));
+ mRoot.setSecureSurfaceState(userId);
}
}
@@ -2255,7 +2244,7 @@ public class WindowManagerService extends IWindowManager.Stub
&& (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
- winAnimator.mSurfaceController.setSecure(isSecureLocked(win));
+ winAnimator.mSurfaceController.setSecure(win.isSecureLocked());
}
win.mRelayoutCalled = true;
@@ -2877,15 +2866,13 @@ public class WindowManagerService extends IWindowManager.Stub
aspectRatio);
}
- public void getStackBounds(int windowingMode, int activityType, Rect bounds) {
- synchronized (mGlobalLock) {
- final ActivityStack stack = mRoot.getStack(windowingMode, activityType);
- if (stack != null) {
- stack.getBounds(bounds);
- return;
- }
- bounds.setEmpty();
+ void getStackBounds(int windowingMode, int activityType, Rect bounds) {
+ final ActivityStack stack = mRoot.getStack(windowingMode, activityType);
+ if (stack != null) {
+ stack.getBounds(bounds);
+ return;
}
+ bounds.setEmpty();
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index a3faa86758cd..fbc5afadac6b 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -44,6 +44,7 @@ import android.window.IWindowOrganizerController;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -51,6 +52,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Server side implementation for the interface for organizing windows
@@ -142,7 +144,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
// operations so we don't end up splitting effects between the WM
// pending transaction and the BLASTSync transaction.
if (syncId >= 0) {
- mBLASTSyncEngine.addToSyncSet(syncId, wc);
+ addToSyncSet(syncId, wc);
}
int containerEffect = applyWindowContainerChange(wc, entry.getValue());
@@ -164,7 +166,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
continue;
}
if (syncId >= 0) {
- mBLASTSyncEngine.addToSyncSet(syncId, wc);
+ addToSyncSet(syncId, wc);
}
effects |= sanitizeAndApplyHierarchyOp(wc, hop);
}
@@ -396,21 +398,33 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return mDisplayAreaOrganizerController;
}
+ @VisibleForTesting
int startSyncWithOrganizer(IWindowContainerTransactionCallback callback) {
int id = mBLASTSyncEngine.startSyncSet(this);
mTransactionCallbacksByPendingSyncId.put(id, callback);
return id;
}
+ @VisibleForTesting
void setSyncReady(int id) {
mBLASTSyncEngine.setReady(id);
}
+ @VisibleForTesting
+ void addToSyncSet(int syncId, WindowContainer wc) {
+ mBLASTSyncEngine.addToSyncSet(syncId, wc);
+ }
+
@Override
- public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
+ public void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady) {
final IWindowContainerTransactionCallback callback =
mTransactionCallbacksByPendingSyncId.get(mSyncId);
+ SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
+ for (WindowContainer container : windowContainersReady) {
+ container.mergeBlastSyncTransaction(mergedTransaction);
+ }
+
try {
callback.onTransactionReady(mSyncId, mergedTransaction);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5fc519c86f11..26a1fea1732b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -176,6 +176,7 @@ import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
import android.annotation.CallSuper;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyCache;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
@@ -241,8 +242,10 @@ import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Set;
import java.util.function.Predicate;
/** A window in the window manager. */
@@ -655,6 +658,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private static final StringBuilder sTmpSB = new StringBuilder();
/**
+ * Whether the next surfacePlacement call should notify that the blast sync is ready.
+ * This is set to true when {@link #finishDrawing(Transaction)} is called so
+ * {@link #onTransactionReady(int, Set)} is called after the next surfacePlacement. This allows
+ * Transactions to get flushed into the syncTransaction before notifying {@link BLASTSyncEngine}
+ * that this WindowState is ready.
+ */
+ private boolean mNotifyBlastOnSurfacePlacement;
+
+ /**
* Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
* of z-order and 1 otherwise.
*/
@@ -705,6 +717,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */
+ private final WindowProcessController mWpcForDisplayConfigChanges;
+
/**
* @return The insets state as requested by the client, i.e. the dispatched insets state
* for which the visibilities are overridden with what the client requested.
@@ -719,8 +733,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void updateRequestedInsetsState(InsetsState state) {
// Only update the sources the client is actually controlling.
- for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
- final InsetsSource source = state.sourceAt(i);
+ for (int i = 0; i < InsetsState.SIZE; i++) {
+ final InsetsSource source = state.peekSource(i);
+ if (source == null) continue;
mRequestedInsetsState.addSource(source);
}
}
@@ -872,6 +887,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mSubLayer = 0;
mInputWindowHandle = null;
mWinAnimator = null;
+ mWpcForDisplayConfigChanges = null;
return;
}
mDeathRecipient = deathRecipient;
@@ -927,6 +943,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
parentWindow.addChild(this, sWindowSubLayerComparator);
}
+
+ // System process or invalid process cannot register to display config change.
+ mWpcForDisplayConfigChanges = (s.mPid == MY_PID || s.mPid < 0)
+ ? null
+ : service.mAtmService.getProcessController(s.mPid, s.mUid);
}
void attach() {
@@ -1744,6 +1765,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
&& mActivityRecord.getActivityType() == ACTIVITY_TYPE_DREAM;
}
+ boolean isSecureLocked() {
+ if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+ return true;
+ }
+ return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId,
+ mOwnerCanAddInternalSystemWindow);
+ }
+
/**
* Whether this window's drawn state might affect the drawn states of the app token.
*
@@ -3505,13 +3534,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
/** @return {@code true} if the process registered to a display as a config listener. */
private boolean registeredForDisplayConfigChanges() {
final WindowState parentWindow = getParentWindow();
- final Session session = parentWindow != null ? parentWindow.mSession : mSession;
- // System process or invalid process cannot register to display config change.
- if (session.mPid == MY_PID || session.mPid < 0) return false;
- WindowProcessController app =
- mWmService.mAtmService.getProcessController(session.mPid, session.mUid);
- if (app == null || !app.registeredForDisplayConfigChanges()) return false;
- return true;
+ final WindowProcessController wpc = parentWindow != null
+ ? parentWindow.mWpcForDisplayConfigChanges
+ : mWpcForDisplayConfigChanges;
+ return wpc != null && wpc.registeredForDisplayConfigChanges();
}
void reportResized() {
@@ -5094,13 +5120,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mWindowFrames.updateLastInsetValues();
}
- @Nullable
@Override
- WindowContainer<WindowState> getAnimatingContainer(int flags, int typesToCheck) {
+ protected boolean isSelfAnimating(int flags, int typesToCheck) {
if (mControllableInsetProvider != null) {
- return null;
+ return false;
}
- return super.getAnimatingContainer(flags, typesToCheck);
+ return super.isSelfAnimating(flags, typesToCheck);
}
void startAnimation(Animation anim) {
@@ -5290,10 +5315,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mWillReplaceWindow;
}
- private void applyDims(Dimmer dimmer) {
+ private void applyDims() {
if (!mAnimatingExit && mAppDied) {
mIsDimming = true;
- dimmer.dimAbove(getSyncTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
+ getDimmer().dimAbove(getSyncTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
} else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) {
// Only show a dim behind when the following is satisfied:
// 1. The window has the flag FLAG_DIM_BEHIND
@@ -5301,7 +5326,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// 3. The WS is considered visible according to the isVisible() method
// 4. The WS is not hidden.
mIsDimming = true;
- dimmer.dimBelow(getSyncTransaction(), this, mAttrs.dimAmount);
+ getDimmer().dimBelow(getSyncTransaction(), this, mAttrs.dimAmount);
}
}
@@ -5325,16 +5350,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
void prepareSurfaces() {
- final Dimmer dimmer = getDimmer();
mIsDimming = false;
- if (dimmer != null) {
- applyDims(dimmer);
- }
+ applyDims();
updateSurfacePosition();
// Send information to SufaceFlinger about the priority of the current window.
updateFrameRateSelectionPriorityIfNeeded();
mWinAnimator.prepareSurfaceLocked(true);
+ notifyBlastSyncTransaction();
super.prepareSurfaces();
}
@@ -5826,6 +5849,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mBLASTSyncTransaction.merge(postDrawTransaction);
}
+ mNotifyBlastOnSurfacePlacement = true;
+ return mWinAnimator.finishDrawingLocked(null);
+ }
+
+ @VisibleForTesting
+ void notifyBlastSyncTransaction() {
+ if (!mNotifyBlastOnSurfacePlacement || mWaitingListener == null) {
+ mNotifyBlastOnSurfacePlacement = false;
+ return;
+ }
+
// If localSyncId is >0 then we are syncing with children and will
// invoke transaction ready from our own #transactionReady callback
// we just need to signal our side of the sync (setReady). But if we
@@ -5833,15 +5867,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// be invoked and we need to invoke it ourself.
if (mLocalSyncId >= 0) {
mBLASTSyncEngine.setReady(mLocalSyncId);
- return mWinAnimator.finishDrawingLocked(null);
+ return;
}
- mWaitingListener.onTransactionReady(mWaitingSyncId, mBLASTSyncTransaction);
- mUsingBLASTSyncTransaction = false;
+ mWaitingListener.onTransactionReady(mWaitingSyncId, Collections.singleton(this));
mWaitingSyncId = 0;
mWaitingListener = null;
- return mWinAnimator.finishDrawingLocked(null);
+ mNotifyBlastOnSurfacePlacement = false;
}
private boolean requestResizeForBlastSync() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 8115ac8c6bef..508d2d477067 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -476,7 +476,7 @@ class WindowStateAnimator {
int flags = SurfaceControl.HIDDEN;
final WindowManager.LayoutParams attrs = w.mAttrs;
- if (mService.isSecureLocked(w)) {
+ if (w.isSecureLocked()) {
flags |= SurfaceControl.SECURE;
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 4c3f73d2d129..925ad0f57f19 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -29,6 +29,7 @@ cc_library_static {
"com_android_server_connectivity_Vpn.cpp",
"com_android_server_ConsumerIrService.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
+ "com_android_server_gpu_GpuService.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
"com_android_server_hdmi_HdmiCecController.cpp",
"com_android_server_input_InputManagerService.cpp",
@@ -98,6 +99,7 @@ cc_defaults {
"libcutils",
"libcrypto",
"liblog",
+ "libgraphicsenv",
"libhardware",
"libhardware_legacy",
"libhidlbase",
diff --git a/services/core/jni/com_android_server_gpu_GpuService.cpp b/services/core/jni/com_android_server_gpu_GpuService.cpp
new file mode 100644
index 000000000000..2359e808d6f6
--- /dev/null
+++ b/services/core/jni/com_android_server_gpu_GpuService.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GpuService-JNI"
+
+#include <binder/IServiceManager.h>
+#include <graphicsenv/IGpuService.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/scoped_utf_chars.h>
+
+namespace {
+
+static android::sp<android::IGpuService> getGpuService() {
+ static const android::sp<android::IBinder> binder =
+ android::defaultServiceManager()->checkService(android::String16("gpu"));
+ if (!binder) {
+ ALOGE("Failed to get gpu service");
+ return nullptr;
+ }
+
+ return interface_cast<android::IGpuService>(binder);
+}
+
+void setUpdatableDriverPath_native(JNIEnv* env, jobject clazz, jstring jDriverPath) {
+ if (jDriverPath == nullptr) {
+ return;
+ }
+ const android::sp<android::IGpuService> gpuService = getGpuService();
+ if (!gpuService) {
+ return;
+ }
+ ScopedUtfChars driverPath(env, jDriverPath);
+ gpuService->setUpdatableDriverPath(driverPath.c_str());
+}
+
+static const JNINativeMethod gGpuServiceMethods[] = {
+ /* name, signature, funcPtr */
+ {"nSetUpdatableDriverPath", "(Ljava/lang/String;)V",
+ reinterpret_cast<void*>(setUpdatableDriverPath_native)},
+};
+
+const char* const kGpuServiceName = "com/android/server/gpu/GpuService";
+
+} // anonymous namespace
+
+namespace android {
+
+int register_android_server_GpuService(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, kGpuServiceName, gGpuServiceMethods,
+ NELEM(gGpuServiceMethods));
+}
+
+} /* namespace android */
diff --git a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
index e51963340ae1..20210abd0ea8 100644
--- a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
+++ b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
@@ -123,6 +123,14 @@ jint com_android_server_storage_AppFuseBridge_add_bridge(
return proxyFd[1].release();
}
+void com_android_server_storage_AppFuseBridge_lock(JNIEnv* env, jobject self) {
+ fuse::FuseBridgeLoop::Lock();
+}
+
+void com_android_server_storage_AppFuseBridge_unlock(JNIEnv* env, jobject self) {
+ fuse::FuseBridgeLoop::Unlock();
+}
+
const JNINativeMethod methods[] = {
{
"native_new",
@@ -143,6 +151,16 @@ const JNINativeMethod methods[] = {
"native_add_bridge",
"(JII)I",
reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_add_bridge)
+ },
+ {
+ "native_lock",
+ "()V",
+ reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_lock)
+ },
+ {
+ "native_unlock",
+ "()V",
+ reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_unlock)
}
};
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index b988bd45d786..e5d2a83479e0 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -63,6 +63,7 @@ int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTrac
int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env);
int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
int register_android_server_AdbDebuggingManager(JNIEnv* env);
+int register_android_server_GpuService(JNIEnv* env);
};
using namespace android;
@@ -119,5 +120,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
register_android_server_stats_pull_StatsPullAtomService(env);
register_android_server_AdbDebuggingManager(env);
+ register_android_server_GpuService(env);
return JNI_VERSION_1_4;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
index f3a693550b38..d616ed30772a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -51,15 +51,15 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
}
@Override
- public boolean getScreenCaptureDisabled(int userHandle) {
+ public boolean isScreenCaptureAllowed(int userHandle, boolean ownerCanAddInternalSystemWindow) {
synchronized (mLock) {
- return mScreenCaptureDisabled.get(userHandle);
+ return !mScreenCaptureDisabled.get(userHandle) || ownerCanAddInternalSystemWindow;
}
}
- public void setScreenCaptureDisabled(int userHandle, boolean disabled) {
+ public void setScreenCaptureAllowed(int userHandle, boolean allowed) {
synchronized (mLock) {
- mScreenCaptureDisabled.put(userHandle, disabled);
+ mScreenCaptureDisabled.put(userHandle, !allowed);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 401649a2e522..c6b93d6ca4f4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7990,7 +7990,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void updateScreenCaptureDisabled(int userHandle, boolean disabled) {
- mPolicyCache.setScreenCaptureDisabled(userHandle, disabled);
+ mPolicyCache.setScreenCaptureAllowed(userHandle, !disabled);
mHandler.post(() -> {
try {
mInjector.getIWindowManager().refreshScreenCaptureDisabled(userHandle);
diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java
index e8ab10124ef8..1801f3bca30e 100644
--- a/services/java/com/android/server/SystemConfigService.java
+++ b/services/java/com/android/server/SystemConfigService.java
@@ -15,6 +15,9 @@
*/
package com.android.server;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+
import android.Manifest;
import android.content.Context;
import android.os.ISystemConfig;
@@ -46,6 +49,19 @@ public class SystemConfigService extends SystemService {
"getDisabledUntilUsedPreInstalledCarrierAssociatedApps requires"
+ " READ_CARRIER_APP_INFO");
return SystemConfig.getInstance()
+ .getDisabledUntilUsedPreinstalledCarrierAssociatedApps().entrySet().stream()
+ .collect(toMap(
+ Map.Entry::getKey,
+ e -> e.getValue().stream().map(app -> app.packageName)
+ .collect(toList())));
+ }
+
+ @Override
+ public Map getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries() {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,
+ "getDisabledUntilUsedPreInstalledCarrierAssociatedAppEntries requires"
+ + " READ_CARRIER_APP_INFO");
+ return SystemConfig.getInstance()
.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
}
};
diff --git a/services/net/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java
index b172c4be7b0d..b17fcaa132a1 100644
--- a/services/net/java/android/net/ip/IpClientCallbacks.java
+++ b/services/net/java/android/net/ip/IpClientCallbacks.java
@@ -68,12 +68,13 @@ public class IpClientCallbacks {
*/
public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
// In general callbacks would not use a parcelable directly (DhcpResultsParcelable), and
- // would use a wrapper instead. But there are already two classes in the tree for DHCP
- // information: DhcpInfo and DhcpResults, and each of them do not expose an appropriate API
- // (they are bags of mutable fields and can't be changed because they are public API and
- // @UnsupportedAppUsage). Adding a third class would cost more than the gain considering
- // that the only client of this callback is WiFi, which will end up converting the results
- // to DhcpInfo anyway.
+ // would use a wrapper instead, because of the lack of safety of stable parcelables. But
+ // there are already two classes in the tree for DHCP information: DhcpInfo and DhcpResults,
+ // and neither of them exposes an appropriate API (they are bags of mutable fields and can't
+ // be changed because they are public API and @UnsupportedAppUsage, being no better than the
+ // stable parcelable). Adding a third class would cost more than the gain considering that
+ // the only client of this callback is WiFi, which will end up converting the results to
+ // DhcpInfo anyway.
}
/**
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index dad001b52b15..41dfade1a09a 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -28,6 +28,14 @@ java_test_host {
":PackageManagerDummyAppVersion1",
":PackageManagerDummyAppVersion2",
":PackageManagerDummyAppVersion3",
+ ":PackageManagerDummyAppVersion4",
":PackageManagerDummyAppOriginalOverride",
+ ":PackageManagerServiceHostTestsResources",
]
}
+
+filegroup {
+ name: "PackageManagerServiceHostTestsResources",
+ srcs: [ "resources/*" ],
+ path: "resources/"
+}
diff --git a/services/tests/PackageManagerServiceTests/host/resources/PackageManagerDummyAppVersion3Invalid.apk b/services/tests/PackageManagerServiceTests/host/resources/PackageManagerDummyAppVersion3Invalid.apk
new file mode 100644
index 000000000000..127886cf8e9e
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/resources/PackageManagerDummyAppVersion3Invalid.apk
Binary files differ
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt
index 4927c45550b5..490f96d8f426 100644
--- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt
@@ -19,6 +19,7 @@ package com.android.server.pm.test
import com.android.internal.util.test.SystemPreparer
import com.android.tradefed.device.ITestDevice
import java.io.File
+import java.io.FileOutputStream
internal fun SystemPreparer.pushApk(file: String, partition: Partition) =
pushResourceFile(file, HostUtils.makePathForApk(file, partition))
@@ -43,4 +44,13 @@ internal object HostUtils {
.resolve(file.nameWithoutExtension)
.resolve(file.name)
.toString()
+
+ fun copyResourceToHostFile(javaResourceName: String, file: File): File {
+ javaClass.classLoader!!.getResource(javaResourceName).openStream().use { input ->
+ FileOutputStream(file).use { output ->
+ input.copyTo(output)
+ }
+ }
+ return file
+ }
}
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt
new file mode 100644
index 000000000000..98e045d0a203
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test
+
+import com.android.internal.util.test.SystemPreparer
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.RuleChain
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+
+@RunWith(DeviceJUnit4ClassRunner::class)
+class InvalidNewSystemAppTest : BaseHostJUnit4Test() {
+
+ companion object {
+ private const val TEST_PKG_NAME = "com.android.server.pm.test.dummy_app"
+ private const val VERSION_ONE = "PackageManagerDummyAppVersion1.apk"
+ private const val VERSION_TWO = "PackageManagerDummyAppVersion2.apk"
+ private const val VERSION_THREE_INVALID = "PackageManagerDummyAppVersion3Invalid.apk"
+ private const val VERSION_FOUR = "PackageManagerDummyAppVersion4.apk"
+
+ @get:ClassRule
+ val deviceRebootRule = SystemPreparer.TestRuleDelegate(true)
+ }
+
+ private val tempFolder = TemporaryFolder()
+ private val preparer: SystemPreparer = SystemPreparer(tempFolder,
+ SystemPreparer.RebootStrategy.START_STOP, deviceRebootRule) { this.device }
+
+ @get:Rule
+ val rules = RuleChain.outerRule(tempFolder).around(preparer)!!
+
+ @Before
+ @After
+ fun uninstallDataPackage() {
+ device.uninstallPackage(TEST_PKG_NAME)
+ }
+
+ @Test
+ fun verify() {
+ // First, push a system app to the device and then update it so there's a data variant
+ val filePath = HostUtils.makePathForApk("PackageManagerDummyApp.apk", Partition.PRODUCT)
+
+ preparer.pushResourceFile(VERSION_ONE, filePath)
+ .reboot()
+
+ val versionTwoFile = HostUtils.copyResourceToHostFile(VERSION_TWO, tempFolder.newFile())
+
+ assertThat(device.installPackage(versionTwoFile, true)).isNull()
+
+ // Then push a bad update to the system, overwriting the existing file as if an OTA occurred
+ preparer.deleteFile(filePath)
+ .pushResourceFile(VERSION_THREE_INVALID, filePath)
+ .reboot()
+
+ // This will remove the package from the device, which is expected
+ assertThat(device.getAppPackageInfo(TEST_PKG_NAME)).isNull()
+
+ // Then check that a user would still be able to install the application manually
+ val versionFourFile = HostUtils.copyResourceToHostFile(VERSION_FOUR, tempFolder.newFile())
+ assertThat(device.installPackage(versionFourFile, true)).isNull()
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp
index 9568faa7dfd0..c9b29275a731 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp
@@ -28,6 +28,11 @@ android_test_helper_app {
}
android_test_helper_app {
+ name: "PackageManagerDummyAppVersion4",
+ manifest: "AndroidManifestVersion4.xml"
+}
+
+android_test_helper_app {
name: "PackageManagerDummyAppOriginalOverride",
manifest: "AndroidManifestOriginalOverride.xml"
}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml
index d772050d7fd0..b492a31349fc 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml
@@ -18,4 +18,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app"
android:versionCode="1"
- />
+ >
+
+ <permission
+ android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
+ android:protectionLevel="normal"
+ />
+
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml
index 53f836b222e6..25e9f8eb2a67 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml
@@ -18,4 +18,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app"
android:versionCode="2"
- />
+ >
+
+ <permission
+ android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
+ android:protectionLevel="normal"
+ />
+
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml
index 90ca9d0ac02c..935f5e62f508 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml
@@ -18,4 +18,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app"
android:versionCode="3"
- />
+ >
+
+ <permission
+ android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
+ android:protectionLevel="normal"
+ />
+
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml
new file mode 100644
index 000000000000..d0643cbb2aeb
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.pm.test.dummy_app"
+ android:versionCode="4"
+ >
+
+ <permission
+ android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
+ android:protectionLevel="normal"
+ />
+
+</manifest>
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 cdafd32cbbb5..fde40aa77a0e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -63,7 +63,6 @@ import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalAnswers.answer;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
@@ -171,7 +170,6 @@ public class MockingOomAdjusterTests {
mock(OomAdjProfiler.class));
doReturn(new ActivityManagerService.ProcessChangeItem()).when(sService)
.enqueueProcessChangeItemLocked(anyInt(), anyInt());
- doReturn(true).when(sService).containsTopUiOrRunningRemoteAnimOrEmptyLocked(any());
sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList,
mock(ActiveUids.class));
sService.mOomAdjuster.mAdjSeq = 10000;
@@ -268,21 +266,6 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
- public void testUpdateOomAdj_DoOne_TopApp_PreemptedByTopUi() {
- ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
- MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
- doReturn(app).when(sService).getTopAppLocked();
- doReturn(false).when(sService).containsTopUiOrRunningRemoteAnimOrEmptyLocked(eq(app));
- sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
- sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- doReturn(null).when(sService).getTopAppLocked();
-
- assertProcStates(app, PROCESS_STATE_TOP, FOREGROUND_APP_ADJ, SCHED_GROUP_DEFAULT);
- }
-
- @SuppressWarnings("GuardedBy")
- @Test
public void testUpdateOomAdj_DoOne_RunningInstrumentation() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
diff --git a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk
index 211e064399a8..bd871ae7488c 100644
--- a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk
+++ b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 4f21ee13a5e2..26230949cda6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -513,6 +513,22 @@ public class AppsFilterTest {
}
@Test
+ public void testSystemUidSecondaryUser_DoesntFilter() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
+
+ assertFalse(appsFilter.shouldFilterApplication(0, null, target, SECONDARY_USER));
+ assertFalse(appsFilter.shouldFilterApplication(
+ UserHandle.getUid(SECONDARY_USER, Process.FIRST_APPLICATION_UID - 1),
+ null, target, SECONDARY_USER));
+ }
+
+ @Test
public void testNonSystemUid_NoCallingSetting_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
@@ -790,7 +806,8 @@ public class AppsFilterTest {
final SparseArray<int[]> systemFilter =
appsFilter.getVisibilityWhitelist(system, USER_ARRAY, mExisting);
- assertThat(toList(systemFilter.get(SYSTEM_USER)), empty());
+ assertThat(toList(systemFilter.get(SYSTEM_USER)),
+ contains(seesNothingAppId, hasProviderAppId, queriesProviderAppId));
final SparseArray<int[]> seesNothingFilter =
appsFilter.getVisibilityWhitelist(seesNothing, USER_ARRAY, mExisting);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 2d45f9ea40c7..7d20da198371 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -213,7 +213,7 @@ public class AppStandbyControllerTests {
}
@Override
- boolean isNonIdleWhitelisted(String packageName) throws RemoteException {
+ boolean isNonIdleWhitelisted(String packageName) {
return mNonIdleWhitelistApps.contains(packageName);
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
index 6991c18ceb82..a2d987fb0a8d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
@@ -149,7 +149,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase {
}
@Test
- public void testPrune_badFileName() {
+ public void testPrune_badFileName_noCrash() {
GregorianCalendar cal = new GregorianCalendar();
cal.setTimeInMillis(10);
int retainDays = 1;
@@ -159,7 +159,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase {
// add 5 files with a creation date of "today", but the file names are bad
for (long i = cal.getTimeInMillis(); i >= 5; i--) {
File file = mock(File.class);
- when(file.getName()).thenReturn(i + ".txt");
+ when(file.getName()).thenReturn(i + ".bak");
AtomicFile af = new AtomicFile(file);
mDataBase.mHistoryFiles.addLast(af);
}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceClientPermissionsTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceClientPermissionsTest.java
index ff2236d25e28..4f092b91220f 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceClientPermissionsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceClientPermissionsTest.java
@@ -227,6 +227,23 @@ public class SliceClientPermissionsTest extends UiServiceTestCase {
assertEquivalent(client, deser);
}
+ @Test(expected = XmlPullParserException.class)
+ public void testReadEmptyFile_ThrowException() throws XmlPullParserException, IOException {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer();
+ serializer.setOutput(output, Encoding.UTF_8.name());
+ // create empty xml document
+ serializer.startDocument(null, true);
+ serializer.endDocument();
+ serializer.flush();
+
+ ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(input, Encoding.UTF_8.name());
+ SliceClientPermissions.createFrom(parser, mock(DirtyTracker.class));
+ // Should throw exception since the xml is empty
+ }
+
private void assertEquivalent(SliceClientPermissions o1, SliceClientPermissions o2) {
assertEquals(o1.getPkg(), o2.getPkg());
ArrayList<SliceAuthority> a1 = new ArrayList<>(o1.getAuthorities());
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 8cf850736cb2..545901e550c1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1236,18 +1236,28 @@ public class DisplayContentTests extends WindowTestsBase {
public void testRecentsNotRotatingWithFixedRotation() {
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
doCallRealMethod().when(displayRotation).updateRotationUnchecked(anyBoolean());
- doCallRealMethod().when(displayRotation).updateOrientation(anyInt(), anyBoolean());
+ // Skip freezing so the unrelated conditions in updateRotationUnchecked won't disturb.
+ doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
final ActivityRecord recentsActivity = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS);
recentsActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+ // Do not rotate if the recents animation is animating on top.
mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recentsActivity);
displayRotation.setRotation((displayRotation.getRotation() + 1) % 4);
assertFalse(displayRotation.updateRotationUnchecked(false));
+ // Rotation can be updated if the recents animation is finished.
mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(false);
assertTrue(displayRotation.updateRotationUnchecked(false));
+
+ // Rotation can be updated if the recents animation is animating but it is not on top, e.g.
+ // switching activities in different orientations by quickstep gesture.
+ mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recentsActivity);
+ mDisplayContent.setFixedRotationLaunchingAppUnchecked(mAppWindow.mActivityRecord);
+ displayRotation.setRotation((displayRotation.getRotation() + 1) % 4);
+ assertTrue(displayRotation.updateRotationUnchecked(false));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 2af98d85b1ca..976ac2323989 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -87,10 +87,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
.setWindow(statusBar, null, null);
statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
final InsetsState state = getController().getInsetsForDispatch(statusBar);
- for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
- final InsetsSource source = state.sourceAt(i);
- assertNotEquals(ITYPE_STATUS_BAR, source.getType());
- }
+ assertNull(state.peekSource(ITYPE_STATUS_BAR));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 4907bdc5e1f0..d6ec78837f7d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -190,7 +190,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
public void testCalculateSnapshotFrame() {
setupSurface(100, 100);
final Rect insets = new Rect(0, 10, 0, 10);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
assertEquals(new Rect(0, 0, 100, 80),
mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
}
@@ -199,7 +199,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
public void testCalculateSnapshotFrame_navBarLeft() {
setupSurface(100, 100);
final Rect insets = new Rect(10, 10, 0, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
assertEquals(new Rect(10, 0, 100, 90),
mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
}
@@ -208,7 +208,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
public void testCalculateSnapshotFrame_waterfall() {
setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
final Rect insets = new Rect(0, 10, 0, 10);
- mSurface.setFrames(new Rect(5, 0, 95, 100), insets, insets);
+ mSurface.setFrames(new Rect(5, 0, 95, 100), insets);
assertEquals(new Rect(0, 0, 90, 90),
mSurface.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
}
@@ -217,7 +217,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
public void testDrawStatusBarBackground() {
setupSurface(100, 100);
final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
@@ -230,7 +230,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
public void testDrawStatusBarBackground_nullFrame() {
setupSurface(100, 100);
final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
@@ -243,7 +243,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
public void testDrawStatusBarBackground_nope() {
setupSurface(100, 100);
final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
@@ -257,7 +257,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Rect insets = new Rect(0, 10, 0, 10);
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
@@ -270,7 +270,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Rect insets = new Rect(10, 10, 0, 0);
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
@@ -283,7 +283,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Rect insets = new Rect(0, 10, 10, 0);
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
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 71dabc56719b..7ce0c1edfb4c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -67,6 +67,7 @@ import android.util.Rational;
import android.view.Display;
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
+import android.window.IWindowContainerTransactionCallback;
import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
@@ -728,7 +729,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
// We should be rejected from the second sync since we are already
// in one.
assertEquals(false, bse.addToSyncSet(id2, task));
- w.finishDrawing(null);
+ finishAndNotifyDrawing(w);
assertEquals(true, bse.addToSyncSet(id2, task));
bse.setReady(id2);
}
@@ -752,7 +753,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
// Since we have a window we have to wait for it to draw to finish sync.
verify(transactionListener, never())
.onTransactionReady(anyInt(), any());
- w.finishDrawing(null);
+ finishAndNotifyDrawing(w);
verify(transactionListener)
.onTransactionReady(anyInt(), any());
}
@@ -820,14 +821,14 @@ public class WindowOrganizerTests extends WindowTestsBase {
int id = bse.startSyncSet(transactionListener);
assertEquals(true, bse.addToSyncSet(id, task));
bse.setReady(id);
- w.finishDrawing(null);
+ finishAndNotifyDrawing(w);
// Since we have a child window we still shouldn't be done.
verify(transactionListener, never())
.onTransactionReady(anyInt(), any());
reset(transactionListener);
- child.finishDrawing(null);
+ finishAndNotifyDrawing(child);
// Ah finally! Done
verify(transactionListener)
.onTransactionReady(anyInt(), any());
@@ -979,4 +980,42 @@ public class WindowOrganizerTests extends WindowTestsBase {
new IRequestFinishCallback.Default());
verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
}
+
+ @Test
+ public void testBLASTCallbackWithMultipleWindows() throws Exception {
+ final ActivityStack stackController = createStack();
+ final Task task = createTask(stackController);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+ final WindowState w1 = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window 1");
+ final WindowState w2 = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window 2");
+ makeWindowVisible(w1);
+ makeWindowVisible(w2);
+
+ IWindowContainerTransactionCallback mockCallback =
+ mock(IWindowContainerTransactionCallback.class);
+ int id = mWm.mAtmService.mWindowOrganizerController.startSyncWithOrganizer(mockCallback);
+
+ mWm.mAtmService.mWindowOrganizerController.addToSyncSet(id, task);
+ mWm.mAtmService.mWindowOrganizerController.setSyncReady(id);
+
+ // Since we have a window we have to wait for it to draw to finish sync.
+ verify(mockCallback, never()).onTransactionReady(anyInt(), any());
+ assertTrue(w1.useBLASTSync());
+ assertTrue(w2.useBLASTSync());
+ finishAndNotifyDrawing(w1);
+
+ // Even though one Window finished drawing, both windows should still be using blast sync
+ assertTrue(w1.useBLASTSync());
+ assertTrue(w2.useBLASTSync());
+
+ finishAndNotifyDrawing(w2);
+ verify(mockCallback).onTransactionReady(anyInt(), any());
+ assertFalse(w1.useBLASTSync());
+ assertFalse(w2.useBLASTSync());
+ }
+
+ private void finishAndNotifyDrawing(WindowState ws) {
+ ws.finishDrawing(null);
+ ws.notifyBlastSyncTransaction();
+ }
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 060ed51951e4..a98da959aff9 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -780,6 +780,22 @@ public class UsageStatsService extends SystemService implements
* Called by the Binder stub.
*/
void reportEvent(Event event, int userId) {
+ final int uid;
+ // Acquire uid outside of mLock for events that need it
+ switch (event.mEventType) {
+ case Event.ACTIVITY_RESUMED:
+ case Event.ACTIVITY_PAUSED:
+ uid = mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId);
+ break;
+ default:
+ uid = 0;
+ }
+
+ if (event.mPackage != null
+ && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) {
+ event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
+ }
+
synchronized (mLock) {
// This should never be called directly when the user is locked
if (!mUserUnlockedStates.get(userId)) {
@@ -792,13 +808,15 @@ public class UsageStatsService extends SystemService implements
final long elapsedRealtime = SystemClock.elapsedRealtime();
- if (event.mPackage != null
- && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) {
- event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
- }
-
switch (event.mEventType) {
case Event.ACTIVITY_RESUMED:
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
+ uid,
+ event.mPackage,
+ event.mClass,
+ FrameworkStatsLog
+ .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
// check if this activity has already been resumed
if (mVisibleActivities.get(event.mInstanceId) != null) break;
mVisibleActivities.put(event.mInstanceId,
@@ -816,13 +834,6 @@ public class UsageStatsService extends SystemService implements
} catch (IllegalArgumentException iae) {
Slog.e(TAG, "Failed to note usage start", iae);
}
- FrameworkStatsLog.write(
- FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
- mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId),
- event.mPackage,
- event.mClass,
- FrameworkStatsLog
- .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
break;
case Event.ACTIVITY_PAUSED:
if (event.mTaskRootPackage == null) {
@@ -839,7 +850,7 @@ public class UsageStatsService extends SystemService implements
}
FrameworkStatsLog.write(
FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
- mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId),
+ uid,
event.mPackage,
event.mClass,
FrameworkStatsLog
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 4606fb4b631c..e57b03098758 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -21,6 +21,8 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.CarrierAssociatedAppEntry;
import android.os.SystemConfigManager;
import android.os.UserHandle;
import android.permission.PermissionManager;
@@ -79,8 +81,8 @@ public final class CarrierAppUtils {
SystemConfigManager config = context.getSystemService(SystemConfigManager.class);
Set<String> systemCarrierAppsDisabledUntilUsed =
config.getDisabledUntilUsedPreinstalledCarrierApps();
- Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
- config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
+ Map<String, List<CarrierAssociatedAppEntry>> systemCarrierAssociatedAppsDisabledUntilUsed =
+ config.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries();
ContentResolver contentResolver = getContentResolverForUser(context, userId);
disableCarrierAppsUntilPrivileged(callingPackage, telephonyManager, contentResolver,
userId, systemCarrierAppsDisabledUntilUsed,
@@ -107,8 +109,8 @@ public final class CarrierAppUtils {
Set<String> systemCarrierAppsDisabledUntilUsed =
config.getDisabledUntilUsedPreinstalledCarrierApps();
- Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
- config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
+ Map<String, List<CarrierAssociatedAppEntry>> systemCarrierAssociatedAppsDisabledUntilUsed =
+ config.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries();
ContentResolver contentResolver = getContentResolverForUser(context, userId);
disableCarrierAppsUntilPrivileged(callingPackage, null /* telephonyManager */,
contentResolver, userId, systemCarrierAppsDisabledUntilUsed,
@@ -138,8 +140,8 @@ public final class CarrierAppUtils {
public static void disableCarrierAppsUntilPrivileged(String callingPackage,
@Nullable TelephonyManager telephonyManager, ContentResolver contentResolver,
int userId, Set<String> systemCarrierAppsDisabledUntilUsed,
- Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed,
- Context context) {
+ Map<String, List<CarrierAssociatedAppEntry>>
+ systemCarrierAssociatedAppsDisabledUntilUsed, Context context) {
PackageManager packageManager = context.getPackageManager();
PermissionManager permissionManager =
(PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE);
@@ -149,12 +151,17 @@ public final class CarrierAppUtils {
return;
}
- Map<String, List<ApplicationInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper(
+ Map<String, List<AssociatedAppInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper(
userId, systemCarrierAssociatedAppsDisabledUntilUsed, context);
List<String> enabledCarrierPackages = new ArrayList<>();
- boolean hasRunOnce = Settings.Secure.getInt(contentResolver,
- Settings.Secure.CARRIER_APPS_HANDLED, 0) == 1;
+ int carrierAppsHandledSdk =
+ Settings.Secure.getInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 0);
+ if (DEBUG) {
+ Log.i(TAG, "Last execution SDK: " + carrierAppsHandledSdk);
+ }
+ boolean hasRunEver = carrierAppsHandledSdk != 0; // SDKs < R used to just set 1 here
+ boolean hasRunForSdk = carrierAppsHandledSdk == Build.VERSION.SDK_INT;
try {
for (ApplicationInfo ai : candidates) {
@@ -166,10 +173,10 @@ public final class CarrierAppUtils {
// add hiddenUntilInstalled flag for carrier apps and associated apps
packageManager.setSystemAppState(
packageName, PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
- List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
+ List<AssociatedAppInfo> associatedAppList = associatedApps.get(packageName);
if (associatedAppList != null) {
- for (ApplicationInfo associatedApp : associatedAppList) {
- packageManager.setSystemAppState(associatedApp.packageName,
+ for (AssociatedAppInfo associatedApp : associatedAppList) {
+ packageManager.setSystemAppState(associatedApp.appInfo.packageName,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
}
}
@@ -184,7 +191,7 @@ public final class CarrierAppUtils {
|| enabledSetting
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
|| (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
- Log.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ Log.i(TAG, "Update state (" + packageName + "): ENABLED for user "
+ userId);
context.createContextAsUser(UserHandle.of(userId), 0)
.getPackageManager()
@@ -200,28 +207,37 @@ public final class CarrierAppUtils {
// Also enable any associated apps for this carrier app.
if (associatedAppList != null) {
- for (ApplicationInfo associatedApp : associatedAppList) {
+ for (AssociatedAppInfo associatedApp : associatedAppList) {
int associatedAppEnabledSetting = context
.createContextAsUser(UserHandle.of(userId), 0)
.getPackageManager()
- .getApplicationEnabledSetting(associatedApp.packageName);
+ .getApplicationEnabledSetting(
+ associatedApp.appInfo.packageName);
+ boolean associatedAppInstalled = (associatedApp.appInfo.flags
+ & ApplicationInfo.FLAG_INSTALLED) != 0;
+ if (DEBUG) {
+ Log.i(TAG, "(hasPrivileges) associated app "
+ + associatedApp.appInfo.packageName + ", enabled = "
+ + associatedAppEnabledSetting + ", installed = "
+ + associatedAppInstalled);
+ }
if (associatedAppEnabledSetting
== PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| associatedAppEnabledSetting
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
- || (associatedApp.flags
- & ApplicationInfo.FLAG_INSTALLED) == 0) {
- Log.i(TAG, "Update associated state(" + associatedApp.packageName
- + "): ENABLED for user " + userId);
+ || !associatedAppInstalled) {
+ Log.i(TAG, "Update associated state ("
+ + associatedApp.appInfo.packageName + "): ENABLED for user "
+ + userId);
context.createContextAsUser(UserHandle.of(userId), 0)
.getPackageManager()
- .setSystemAppState(associatedApp.packageName,
+ .setSystemAppState(associatedApp.appInfo.packageName,
PackageManager.SYSTEM_APP_STATE_INSTALLED);
context.createPackageContextAsUser(
callingPackage, 0, UserHandle.of(userId))
.getPackageManager()
.setApplicationEnabledSetting(
- associatedApp.packageName,
+ associatedApp.appInfo.packageName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
@@ -236,7 +252,7 @@ public final class CarrierAppUtils {
if (!isUpdatedSystemApp(ai) && enabledSetting
== PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
&& (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
- Log.i(TAG, "Update state(" + packageName
+ Log.i(TAG, "Update state (" + packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
context.createContextAsUser(UserHandle.of(userId), 0)
.getPackageManager()
@@ -244,37 +260,56 @@ public final class CarrierAppUtils {
packageName, PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
}
- // Also disable any associated apps for this carrier app if this is the first
- // run. We avoid doing this a second time because it is brittle to rely on the
- // distinction between "default" and "enabled".
- if (!hasRunOnce) {
- if (associatedAppList != null) {
- for (ApplicationInfo associatedApp : associatedAppList) {
- int associatedAppEnabledSetting = context
- .createContextAsUser(UserHandle.of(userId), 0)
+ // Associated apps are more brittle, because we can't rely on the distinction
+ // between "default" and "enabled". To account for this, we have two cases:
+ // 1. We've never run before, so we're fine to disable all associated apps.
+ // 2. We've run before, but not on this SDK version, so we will only operate on
+ // apps with addedInSdk in the range (lastHandledSdk, currentSdk].
+ // Otherwise, don't touch the associated apps.
+ if (associatedAppList != null) {
+ for (AssociatedAppInfo associatedApp : associatedAppList) {
+ boolean allowDisable = !hasRunEver || (!hasRunForSdk
+ && associatedApp.addedInSdk
+ != CarrierAssociatedAppEntry.SDK_UNSPECIFIED
+ && associatedApp.addedInSdk > carrierAppsHandledSdk
+ && associatedApp.addedInSdk <= Build.VERSION.SDK_INT);
+ int associatedAppEnabledSetting = context
+ .createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .getApplicationEnabledSetting(
+ associatedApp.appInfo.packageName);
+ boolean associatedAppInstalled = (associatedApp.appInfo.flags
+ & ApplicationInfo.FLAG_INSTALLED) != 0;
+ if (DEBUG) {
+ Log.i(TAG, "(!hasPrivileges) associated app "
+ + associatedApp.appInfo.packageName + ", allowDisable = "
+ + allowDisable + ", addedInSdk = "
+ + associatedApp.addedInSdk + ", enabled = "
+ + associatedAppEnabledSetting + ", installed = "
+ + associatedAppInstalled);
+ }
+ if (allowDisable
+ && associatedAppEnabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ && associatedAppInstalled) {
+ Log.i(TAG,
+ "Update associated state ("
+ + associatedApp.appInfo.packageName
+ + "): DISABLED_UNTIL_USED for user " + userId);
+ context.createContextAsUser(UserHandle.of(userId), 0)
.getPackageManager()
- .getApplicationEnabledSetting(associatedApp.packageName);
- if (associatedAppEnabledSetting
- == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- && (associatedApp.flags
- & ApplicationInfo.FLAG_INSTALLED) != 0) {
- Log.i(TAG,
- "Update associated state(" + associatedApp.packageName
- + "): DISABLED_UNTIL_USED for user " + userId);
- context.createContextAsUser(UserHandle.of(userId), 0)
- .getPackageManager()
- .setSystemAppState(associatedApp.packageName,
- PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
- }
+ .setSystemAppState(associatedApp.appInfo.packageName,
+ PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
}
}
}
}
}
- // Mark the execution so we do not disable apps again.
- if (!hasRunOnce) {
- Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 1);
+ // Mark the execution so we do not disable apps again on this SDK version.
+ if (!hasRunEver || !hasRunForSdk) {
+ Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED,
+ Build.VERSION.SDK_INT);
}
if (!enabledCarrierPackages.isEmpty()) {
@@ -360,28 +395,28 @@ public final class CarrierAppUtils {
return apps;
}
- private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper(
- int userId, Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed,
- Context context) {
+ private static Map<String, List<AssociatedAppInfo>> getDefaultCarrierAssociatedAppsHelper(
+ int userId, Map<String, List<CarrierAssociatedAppEntry>>
+ systemCarrierAssociatedAppsDisabledUntilUsed, Context context) {
int size = systemCarrierAssociatedAppsDisabledUntilUsed.size();
- Map<String, List<ApplicationInfo>> associatedApps = new ArrayMap<>(size);
- for (Map.Entry<String, List<String>> entry
+ Map<String, List<AssociatedAppInfo>> associatedApps = new ArrayMap<>(size);
+ for (Map.Entry<String, List<CarrierAssociatedAppEntry>> entry
: systemCarrierAssociatedAppsDisabledUntilUsed.entrySet()) {
String carrierAppPackage = entry.getKey();
- List<String> associatedAppPackages = entry.getValue();
+ List<CarrierAssociatedAppEntry> associatedAppPackages = entry.getValue();
for (int j = 0; j < associatedAppPackages.size(); j++) {
+ CarrierAssociatedAppEntry associatedApp = associatedAppPackages.get(j);
ApplicationInfo ai =
- getApplicationInfoIfSystemApp(
- userId, associatedAppPackages.get(j), context);
+ getApplicationInfoIfSystemApp(userId, associatedApp.packageName, context);
// Only update enabled state for the app on /system. Once it has been updated we
// shouldn't touch it.
if (ai != null && !isUpdatedSystemApp(ai)) {
- List<ApplicationInfo> appList = associatedApps.get(carrierAppPackage);
+ List<AssociatedAppInfo> appList = associatedApps.get(carrierAppPackage);
if (appList == null) {
appList = new ArrayList<>();
associatedApps.put(carrierAppPackage, appList);
}
- appList.add(ai);
+ appList.add(new AssociatedAppInfo(ai, associatedApp.addedInSdk));
}
}
}
@@ -406,4 +441,15 @@ public final class CarrierAppUtils {
}
return null;
}
+
+ private static final class AssociatedAppInfo {
+ public final ApplicationInfo appInfo;
+ // Might be CarrierAssociatedAppEntry.SDK_UNSPECIFIED.
+ public final int addedInSdk;
+
+ AssociatedAppInfo(ApplicationInfo appInfo, int addedInSdk) {
+ this.appInfo = appInfo;
+ this.addedInSdk = addedInSdk;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 53aad2351a32..3d455d51dd7f 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1385,6 +1385,14 @@ public class CarrierConfigManager {
public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
/**
+ * To override wifi calling's carrier name string using ef_pnn from sim card when SPN in empty.
+ *
+ * @hide
+ */
+ public static final String KEY_WFC_CARRIER_NAME_OVERRIDE_BY_PNN_BOOL =
+ "wfc_carrier_name_override_by_pnn_bool";
+
+ /**
* Override the SPN Display Condition 2 integer bits (lsb). B2, B1 is the last two bits of the
* spn display condition coding.
*
@@ -4008,6 +4016,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
+ sDefaults.putBoolean(KEY_WFC_CARRIER_NAME_OVERRIDE_BY_PNN_BOOL, false);
sDefaults.putInt(KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT, -1);
sDefaults.putStringArray(KEY_SPDI_OVERRIDE_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_PNN_OVERRIDE_STRING_ARRAY, null);
diff --git a/tests/net/common/java/android/net/DhcpInfoTest.java b/tests/net/common/java/android/net/DhcpInfoTest.java
index bd5533f33910..4d45ad72a9b8 100644
--- a/tests/net/common/java/android/net/DhcpInfoTest.java
+++ b/tests/net/common/java/android/net/DhcpInfoTest.java
@@ -16,8 +16,7 @@
package android.net;
-import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL;
-
+import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTL;
import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip;
diff --git a/tests/net/java/android/net/DnsPacketTest.java b/tests/net/java/android/net/DnsPacketTest.java
deleted file mode 100644
index 975abf416944..000000000000
--- a/tests/net/java/android/net/DnsPacketTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-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.List;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class DnsPacketTest {
- private void assertHeaderParses(DnsPacket.DnsHeader header, int id, int flag,
- int qCount, int aCount, int nsCount, int arCount) {
- assertEquals(header.id, id);
- assertEquals(header.flags, flag);
- assertEquals(header.getRecordCount(DnsPacket.QDSECTION), qCount);
- assertEquals(header.getRecordCount(DnsPacket.ANSECTION), aCount);
- assertEquals(header.getRecordCount(DnsPacket.NSSECTION), nsCount);
- assertEquals(header.getRecordCount(DnsPacket.ARSECTION), arCount);
- }
-
- private void assertRecordParses(DnsPacket.DnsRecord record, String dname,
- int dtype, int dclass, int ttl, byte[] rr) {
- assertEquals(record.dName, dname);
- assertEquals(record.nsType, dtype);
- assertEquals(record.nsClass, dclass);
- assertEquals(record.ttl, ttl);
- assertTrue(Arrays.equals(record.getRR(), rr));
- }
-
- class TestDnsPacket extends DnsPacket {
- TestDnsPacket(byte[] data) throws ParseException {
- super(data);
- }
-
- public DnsHeader getHeader() {
- return mHeader;
- }
- public List<DnsRecord> getRecordList(int secType) {
- return mRecords[secType];
- }
- }
-
- @Test
- public void testNullDisallowed() {
- try {
- new TestDnsPacket(null);
- fail("Exception not thrown for null byte array");
- } catch (ParseException e) {
- }
- }
-
- @Test
- public void testV4Answer() throws Exception {
- final byte[] v4blob = new byte[] {
- /* Header */
- 0x55, 0x66, /* Transaction ID */
- (byte) 0x81, (byte) 0x80, /* Flags */
- 0x00, 0x01, /* Questions */
- 0x00, 0x01, /* Answer RRs */
- 0x00, 0x00, /* Authority RRs */
- 0x00, 0x00, /* Additional RRs */
- /* Queries */
- 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65,
- 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */
- 0x00, 0x01, /* Type */
- 0x00, 0x01, /* Class */
- /* Answers */
- (byte) 0xc0, 0x0c, /* Name */
- 0x00, 0x01, /* Type */
- 0x00, 0x01, /* Class */
- 0x00, 0x00, 0x01, 0x2b, /* TTL */
- 0x00, 0x04, /* Data length */
- (byte) 0xac, (byte) 0xd9, (byte) 0xa1, (byte) 0x84 /* Address */
- };
- TestDnsPacket packet = new TestDnsPacket(v4blob);
-
- // Header part
- assertHeaderParses(packet.getHeader(), 0x5566, 0x8180, 1, 1, 0, 0);
-
- // Record part
- List<DnsPacket.DnsRecord> qdRecordList =
- packet.getRecordList(DnsPacket.QDSECTION);
- assertEquals(qdRecordList.size(), 1);
- assertRecordParses(qdRecordList.get(0), "www.google.com", 1, 1, 0, null);
-
- List<DnsPacket.DnsRecord> anRecordList =
- packet.getRecordList(DnsPacket.ANSECTION);
- assertEquals(anRecordList.size(), 1);
- assertRecordParses(anRecordList.get(0), "www.google.com", 1, 1, 0x12b,
- new byte[]{ (byte) 0xac, (byte) 0xd9, (byte) 0xa1, (byte) 0x84 });
- }
-
- @Test
- public void testV6Answer() throws Exception {
- final byte[] v6blob = new byte[] {
- /* Header */
- 0x77, 0x22, /* Transaction ID */
- (byte) 0x81, (byte) 0x80, /* Flags */
- 0x00, 0x01, /* Questions */
- 0x00, 0x01, /* Answer RRs */
- 0x00, 0x00, /* Authority RRs */
- 0x00, 0x00, /* Additional RRs */
- /* Queries */
- 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65,
- 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */
- 0x00, 0x1c, /* Type */
- 0x00, 0x01, /* Class */
- /* Answers */
- (byte) 0xc0, 0x0c, /* Name */
- 0x00, 0x1c, /* Type */
- 0x00, 0x01, /* Class */
- 0x00, 0x00, 0x00, 0x37, /* TTL */
- 0x00, 0x10, /* Data length */
- 0x24, 0x04, 0x68, 0x00, 0x40, 0x05, 0x08, 0x0d,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04 /* Address */
- };
- TestDnsPacket packet = new TestDnsPacket(v6blob);
-
- // Header part
- assertHeaderParses(packet.getHeader(), 0x7722, 0x8180, 1, 1, 0, 0);
-
- // Record part
- List<DnsPacket.DnsRecord> qdRecordList =
- packet.getRecordList(DnsPacket.QDSECTION);
- assertEquals(qdRecordList.size(), 1);
- assertRecordParses(qdRecordList.get(0), "www.google.com", 28, 1, 0, null);
-
- List<DnsPacket.DnsRecord> anRecordList =
- packet.getRecordList(DnsPacket.ANSECTION);
- assertEquals(anRecordList.size(), 1);
- assertRecordParses(anRecordList.get(0), "www.google.com", 28, 1, 0x37,
- new byte[]{ 0x24, 0x04, 0x68, 0x00, 0x40, 0x05, 0x08, 0x0d,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04 });
- }
-}
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index 7748288aeb05..3158cc8637e4 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -16,10 +16,24 @@
package android.net;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.AF_UNIX;
+import static android.system.OsConstants.EPERM;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+
import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.system.ErrnoException;
+import android.system.Os;
+
import androidx.test.runner.AndroidJUnit4;
+import libcore.io.IoUtils;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -125,4 +139,50 @@ public class NetworkUtilsTest {
assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
NetworkUtils.routedIPv6AddressCount(set));
}
+
+ private static void expectSocketSuccess(String msg, int domain, int type) {
+ try {
+ IoUtils.closeQuietly(Os.socket(domain, type, 0));
+ } catch (ErrnoException e) {
+ fail(msg + e.getMessage());
+ }
+ }
+
+ private static void expectSocketPemissionError(String msg, int domain, int type) {
+ try {
+ IoUtils.closeQuietly(Os.socket(domain, type, 0));
+ fail(msg);
+ } catch (ErrnoException e) {
+ assertEquals(msg, e.errno, EPERM);
+ }
+ }
+
+ private static void expectHasNetworking() {
+ expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+ AF_UNIX, SOCK_STREAM);
+ expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException",
+ AF_INET, SOCK_DGRAM);
+ expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException",
+ AF_INET6, SOCK_DGRAM);
+ }
+
+ private static void expectNoNetworking() {
+ expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+ AF_UNIX, SOCK_STREAM);
+ expectSocketPemissionError(
+ "Creating a AF_INET socket should have thrown ErrnoException(EPERM)",
+ AF_INET, SOCK_DGRAM);
+ expectSocketPemissionError(
+ "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)",
+ AF_INET6, SOCK_DGRAM);
+ }
+
+ @Test
+ public void testSetAllowNetworkingForProcess() {
+ expectHasNetworking();
+ NetworkUtils.setAllowNetworkingForProcess(false);
+ expectNoNetworking();
+ NetworkUtils.setAllowNetworkingForProcess(true);
+ expectHasNetworking();
+ }
}
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index f0555e6ec93e..e253ae25659e 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -114,7 +114,6 @@ rule fi.iki.elonen.** com.android.wifi.x.@0
## used by both framework-wifi and service-wifi ##
rule android.content.pm.BaseParceledListSlice* com.android.wifi.x.@0
rule android.content.pm.ParceledListSlice* com.android.wifi.x.@0
-rule android.net.shared.Inet4AddressUtils* com.android.wifi.x.@0
rule android.net.util.MacAddressUtils* com.android.wifi.x.@0
rule android.net.util.nsd.DnsSdTxtRecord* com.android.wifi.x.@0
rule android.os.HandlerExecutor* com.android.wifi.x.@0
@@ -123,3 +122,5 @@ rule com.android.internal.util.AsyncChannel* com.android.wifi.x.@0
rule com.android.internal.util.AsyncService* com.android.wifi.x.@0
rule com.android.internal.util.Preconditions* com.android.wifi.x.@0
rule com.android.internal.util.Protocol* com.android.wifi.x.@0
+
+rule com.android.net.module.util.** com.android.wifi.x.@0
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 7b86b084baab..abd573f4bea9 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -769,6 +769,10 @@ public class WifiEnterpriseConfig implements Parcelable {
* certificate when the config is saved and removing the certificate when
* the config is removed.
*
+ * Note: If no certificate is set for an Enterprise configuration, either by not calling this
+ * API (or the {@link #setCaCertificates(X509Certificate[])}, or by calling it with null, then
+ * the server certificate validation is skipped - which means that the connection is not secure.
+ *
* @param cert X.509 CA certificate
* @throws IllegalArgumentException if not a CA certificate
*/
@@ -808,6 +812,11 @@ public class WifiEnterpriseConfig implements Parcelable {
* certificates when the config is saved and removing the certificates when
* the config is removed.
*
+ * Note: If no certificates are set for an Enterprise configuration, either by not calling this
+ * API (or the {@link #setCaCertificate(X509Certificate)}, or by calling it with null, then the
+ * server certificate validation is skipped - which means that the
+ * connection is not secure.
+ *
* @param certs X.509 CA certificates
* @throws IllegalArgumentException if any of the provided certificates is
* not a CA certificate
@@ -859,6 +868,13 @@ public class WifiEnterpriseConfig implements Parcelable {
* like /etc/ssl/certs. If configured, these certificates are added to the
* list of trusted CAs. ca_cert may also be included in that case, but it is
* not required.
+ *
+ * Note: If no certificate path is set for an Enterprise configuration, either by not calling
+ * this API, or by calling it with null, and no certificate is set by
+ * {@link #setCaCertificate(X509Certificate)} or {@link #setCaCertificates(X509Certificate[])},
+ * then the server certificate validation is skipped - which means that the connection is not
+ * secure.
+ *
* @param path The path for CA certificate files, or empty string to clear.
* @hide
*/
@@ -868,7 +884,7 @@ public class WifiEnterpriseConfig implements Parcelable {
}
/**
- * Get the domain_suffix_match value. See setDomSuffixMatch.
+ * Get the ca_path directive from wpa_supplicant.
* @return The path for CA certificate files, or an empty string if unset.
* @hide
*/
@@ -1061,6 +1077,12 @@ public class WifiEnterpriseConfig implements Parcelable {
/**
* Set alternate subject match. This is the substring to be matched against the
* alternate subject of the authentication server certificate.
+ *
+ * Note: If no alternate subject is set for an Enterprise configuration, either by not calling
+ * this API, or by calling it with null, or not setting domain suffix match using the
+ * {@link #setDomainSuffixMatch(String)}, then the server certificate validation is incomplete -
+ * which means that the connection is not secure.
+ *
* @param altSubjectMatch substring to be matched, for example
* DNS:server.example.com;EMAIL:server@example.com
*/
@@ -1095,6 +1117,12 @@ public class WifiEnterpriseConfig implements Parcelable {
* ORed ogether.
* <p>For example, domain_suffix_match=example.com would match test.example.com but would not
* match test-example.com.
+ *
+ * Note: If no domain suffix is set for an Enterprise configuration, either by not calling this
+ * API, or by calling it with null, or not setting alternate subject match using the
+ * {@link #setAltSubjectMatch(String)}, then the server certificate
+ * validation is incomplete - which means that the connection is not secure.
+ *
* @param domain The domain value
*/
public void setDomainSuffixMatch(String domain) {
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index b841921355e9..53883674e058 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -22,12 +22,13 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkInfo.DetailedState;
-import android.net.shared.Inet4AddressUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import com.android.net.module.util.Inet4AddressUtils;
+
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 5f46cb3fa642..1b0497a0ecd5 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1894,9 +1894,10 @@ public class WifiManager {
* for a detailed explanation of the parameters.
* When the device decides to connect to one of the provided network suggestions, platform sends
* a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if
- * the network was created with {@link WifiNetworkSuggestion.Builder
- * #setIsAppInteractionRequired()} flag set and the app holds
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission.
+ * the network was created with
+ * {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(boolean)} flag set and the
+ * app holds {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}
+ * permission.
*<p>
* NOTE:
* <li> These networks are just a suggestion to the platform. The platform will ultimately