summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java29
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java80
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java91
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java13
-rw-r--r--apex/media/framework/java/android/media/MediaParser.java80
-rw-r--r--apex/statsd/framework/Android.bp3
-rw-r--r--api/test-current.txt15
-rw-r--r--cmds/statsd/Android.bp46
-rw-r--r--cmds/statsd/src/atom_field_options.proto2
-rw-r--r--cmds/statsd/src/atoms.proto29
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp8
-rw-r--r--core/java/android/app/Activity.java5
-rw-r--r--core/java/android/app/ActivityView.java18
-rw-r--r--core/java/android/app/AppOpsManager.java14
-rw-r--r--core/java/android/app/AppOpsManagerInternal.java8
-rw-r--r--core/java/android/app/ApplicationPackageManager.java17
-rw-r--r--core/java/android/app/ContextImpl.java7
-rw-r--r--core/java/android/app/DownloadManager.java56
-rw-r--r--core/java/android/app/IActivityManager.aidl6
-rw-r--r--core/java/android/app/UiAutomationConnection.java2
-rw-r--r--core/java/android/app/usage/NetworkStatsManager.java43
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java1
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java11
-rw-r--r--core/java/android/hardware/camera2/params/MandatoryStreamCombination.java21
-rw-r--r--core/java/android/inputmethodservice/InlineSuggestionSession.java20
-rw-r--r--core/java/android/inputmethodservice/InlineSuggestionSessionController.java1
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java4
-rwxr-xr-xcore/java/android/os/Build.java25
-rw-r--r--core/java/android/os/StrictMode.java63
-rw-r--r--core/java/android/os/UserManager.java83
-rw-r--r--core/java/android/os/strictmode/Violation.java51
-rw-r--r--core/java/android/permission/IPermissionManager.aidl2
-rwxr-xr-xcore/java/android/provider/Settings.java2
-rw-r--r--core/java/android/service/autofill/IInlineSuggestionRenderService.aidl8
-rw-r--r--core/java/android/service/autofill/InlineSuggestionRenderService.java49
-rw-r--r--core/java/android/service/controls/ControlsProviderService.java4
-rw-r--r--core/java/android/view/ImeInsetsSourceConsumer.java10
-rw-r--r--core/java/android/view/InsetsAnimationControlCallbacks.java12
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java14
-rw-r--r--core/java/android/view/InsetsAnimationThreadControlRunner.java5
-rw-r--r--core/java/android/view/InsetsController.java92
-rw-r--r--core/java/android/view/InsetsSource.java5
-rw-r--r--core/java/android/view/InsetsSourceConsumer.java18
-rw-r--r--core/java/android/view/MotionEvent.java29
-rw-r--r--core/java/android/view/SurfaceControl.java145
-rw-r--r--core/java/android/view/SurfaceView.java68
-rw-r--r--core/java/android/view/View.java8
-rw-r--r--core/java/android/view/ViewConfiguration.java5
-rw-r--r--core/java/android/view/ViewGroup.java81
-rw-r--r--core/java/android/view/ViewRootImpl.java4
-rw-r--r--core/java/android/view/ViewRootInsetsControllerHost.java13
-rw-r--r--core/java/android/view/autofill/AutofillId.java2
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java21
-rw-r--r--core/java/android/widget/Editor.java17
-rw-r--r--core/java/android/widget/inline/InlineContentView.java170
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java23
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl7
-rw-r--r--core/java/com/android/internal/app/UnlaunchableAppActivity.java7
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodDebug.java6
-rw-r--r--core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java9
-rw-r--r--core/java/com/android/internal/inputmethod/StartInputReason.java30
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl1
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl1
-rw-r--r--core/java/com/android/internal/widget/ConversationLayout.java3
-rw-r--r--core/java/com/android/internal/widget/MessagingLayout.java1
-rw-r--r--core/java/com/android/internal/widget/MessagingLinearLayout.java20
-rw-r--r--core/proto/android/stats/connectivity/tethering.proto2
-rw-r--r--core/res/res/drawable/chooser_action_button_bg.xml4
-rw-r--r--core/res/res/layout/chooser_action_button.xml4
-rw-r--r--core/res/res/layout/notification_template_material_conversation.xml2
-rw-r--r--core/res/res/values-ar/strings.xml4
-rw-r--r--core/res/res/values-bs/strings.xml2
-rw-r--r--core/res/res/values-cs/strings.xml2
-rw-r--r--core/res/res/values-en-rCA/strings.xml4
-rw-r--r--core/res/res/values-en-rIN/strings.xml6
-rw-r--r--core/res/res/values-night/colors.xml1
-rw-r--r--core/res/res/values-pt-rBR/strings.xml2
-rw-r--r--core/res/res/values-pt/strings.xml2
-rw-r--r--core/res/res/values-zh-rCN/strings.xml4
-rw-r--r--core/res/res/values/colors.xml1
-rw-r--r--core/res/res/values/public.xml4
-rw-r--r--core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java18
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java18
-rw-r--r--libs/androidfw/Idmap.cpp2
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h4
-rw-r--r--location/java/android/location/AbstractListenerManager.java8
-rw-r--r--location/java/android/location/LocationManager.java6
-rw-r--r--media/java/android/media/AudioDeviceInfo.java3
-rwxr-xr-xmedia/java/android/media/AudioManager.java24
-rw-r--r--media/java/android/media/AudioTrack.java2
-rw-r--r--media/java/android/media/IMediaRouter2.aidl5
-rw-r--r--media/java/android/media/IMediaRouterService.aidl11
-rw-r--r--media/java/android/media/MediaCodec.java2
-rw-r--r--media/java/android/media/MediaRouter2.java347
-rw-r--r--media/java/android/media/MediaRouter2Manager.java9
-rw-r--r--media/java/android/media/RoutingSessionInfo.java2
-rw-r--r--media/jni/android_media_tv_Tuner.cpp2
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java74
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java20
-rw-r--r--packages/OsuLogin/res/values-af/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-am/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ar/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-as/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-az/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-b+sr+Latn/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-be/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-bg/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-bn/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-bs/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ca/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-cs/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-da/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-de/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-el/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-en-rAU/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-en-rCA/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-en-rGB/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-en-rIN/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-en-rXC/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-es-rUS/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-es/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-et/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-eu/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-fa/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-fi/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-fr-rCA/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-fr/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-gl/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-gu/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-hi/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-hr/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-hu/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-hy/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-in/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-is/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-it/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-iw/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ja/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ka/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-kk/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-km/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-kn/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ko/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ky/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-lo/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-lt/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-lv/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-mk/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ml/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-mn/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-mr/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ms/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-my/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-nb/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ne/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-nl/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-or/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-pa/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-pl/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-pt-rBR/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-pt-rPT/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-pt/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ro/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ru/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-si/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-sk/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-sl/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-sq/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-sr/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-sv/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-sw/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ta/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-te/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-th/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-tl/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-tr/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-uk/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-ur/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-uz/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-vi/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-zh-rCN/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-zh-rHK/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-zh-rTW/strings.xml7
-rw-r--r--packages/OsuLogin/res/values-zu/strings.xml7
-rw-r--r--packages/SettingsLib/AdaptiveIcon/res/values-night/colors.xml19
-rw-r--r--packages/SoundPicker/res/values-af/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-b+sr+Latn/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-bg/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-bs/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-ca/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-cs/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-da/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-el/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-es-rUS/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-es/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-et/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-fa/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-fi/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-gl/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-hr/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-is/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-ja/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-ka/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-kn/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-lo/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-mk/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-my/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-nb/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-nl/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-pt-rBR/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-pt-rPT/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-pt/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-ro/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-ru/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-si/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-sl/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-sq/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-sr/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-sw/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-tl/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-tr/strings.xml3
-rw-r--r--packages/SoundPicker/res/values-zu/strings.xml3
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java6
-rw-r--r--packages/SystemUI/res-keyguard/drawable/qs_media_seamless_background.xml26
-rw-r--r--packages/SystemUI/res-keyguard/layout/qs_media_divider.xml7
-rw-r--r--packages/SystemUI/res/layout/controls_management.xml2
-rw-r--r--packages/SystemUI/res/layout/media_carousel.xml6
-rw-r--r--packages/SystemUI/res/layout/media_carousel_settings_button.xml29
-rw-r--r--packages/SystemUI/res/layout/media_view.xml52
-rw-r--r--packages/SystemUI/res/layout/qs_panel.xml2
-rw-r--r--packages/SystemUI/res/layout/tv_audio_recording_indicator.xml4
-rw-r--r--packages/SystemUI/res/values-af/strings.xml63
-rw-r--r--packages/SystemUI/res/values-am/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml15
-rw-r--r--packages/SystemUI/res/values-as/strings.xml12
-rw-r--r--packages/SystemUI/res/values-az/strings.xml3
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml63
-rw-r--r--packages/SystemUI/res/values-be/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml60
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml12
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml63
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml63
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml63
-rw-r--r--packages/SystemUI/res/values-da/strings.xml63
-rw-r--r--packages/SystemUI/res/values-de/strings.xml15
-rw-r--r--packages/SystemUI/res/values-el/strings.xml63
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml12
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml12
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml12
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml12
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml12
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml69
-rw-r--r--packages/SystemUI/res/values-es/strings.xml63
-rw-r--r--packages/SystemUI/res/values-et/strings.xml63
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml15
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml63
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml63
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml21
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml63
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml12
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml15
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml63
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml15
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml3
-rw-r--r--packages/SystemUI/res/values-in/strings.xml3
-rw-r--r--packages/SystemUI/res/values-is/strings.xml63
-rw-r--r--packages/SystemUI/res/values-it/strings.xml15
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml63
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml63
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-km/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml60
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml60
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml15
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml15
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml63
-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.xml12
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml3
-rw-r--r--packages/SystemUI/res/values-my/strings.xml63
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml63
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml12
-rw-r--r--packages/SystemUI/res/values-night/colors.xml2
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml63
-rw-r--r--packages/SystemUI/res/values-or/strings.xml12
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml12
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml15
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml63
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml63
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml63
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml51
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml51
-rw-r--r--packages/SystemUI/res/values-si/strings.xml60
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml63
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml63
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml63
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml63
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml15
-rw-r--r--packages/SystemUI/res/values-te/strings.xml12
-rw-r--r--packages/SystemUI/res/values-th/strings.xml15
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml63
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml63
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml12
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml12
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml15
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml15
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml15
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml63
-rw-r--r--packages/SystemUI/res/values/colors.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/res/xml/media_collapsed.xml33
-rw-r--r--packages/SystemUI/res/xml/media_expanded.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java129
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/AnimatableScaleMatrix.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt (renamed from packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt)287
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt516
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaData.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHost.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaScrollView.kt100
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt54
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/UnboundHorizontalScrollView.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetail.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationAppOpsEvent.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationControlsEvent.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickswitchOrientedNavHandle.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java)40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt151
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java43
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java79
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java3
-rw-r--r--packages/Tethering/Android.bp1
-rw-r--r--packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java8
-rw-r--r--packages/Tethering/res/values/config.xml7
-rw-r--r--packages/Tethering/res/values/overlayable.xml1
-rw-r--r--packages/Tethering/src/android/net/ip/IpServer.java3
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java33
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/Tethering.java6
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java7
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java39
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java96
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java8
-rw-r--r--services/accessibility/java/com/android/server/accessibility/FullScreenMagnificationGestureHandler.java52
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java256
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java9
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/GestureUtils.java22
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java23
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java117
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java9
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java11
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java39
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java12
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java38
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java7
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java5
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java6
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java12
-rw-r--r--services/core/Android.bp2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java32
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java57
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java10
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java56
-rw-r--r--services/core/java/com/android/server/am/PendingIntentController.java98
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java4
-rw-r--r--services/core/java/com/android/server/am/UserController.java18
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java47
-rwxr-xr-xservices/core/java/com/android/server/audio/AudioService.java265
-rw-r--r--services/core/java/com/android/server/connectivity/DnsManager.java19
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkDiagnostics.java208
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java278
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java1
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiLogger.java6
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java15
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java68
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java10
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java4
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2Provider.java1
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java105
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java316
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java16
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java5
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java76
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java2
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java8
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java233
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java2
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java10
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/README.md19
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java123
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java107
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java53
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java13
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java11
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java13
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java24
-rw-r--r--services/core/java/com/android/server/wm/AppTaskImpl.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java73
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java3
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java50
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java6
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java2
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java21
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java6
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java18
-rw-r--r--services/core/java/com/android/server/wm/Task.java14
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java42
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java15
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp4
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java5
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java52
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/FullScreenMagnificationGestureHandlerTest.java192
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java30
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java133
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java17
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java43
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java46
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java256
-rw-r--r--tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java9
-rw-r--r--tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java6
-rw-r--r--tests/StagedInstallTest/Android.bp31
-rw-r--r--tests/StagedInstallTest/StagedInstallInternalTest.xml33
-rw-r--r--tests/StagedInstallTest/TEST_MAPPING7
-rw-r--r--tests/StagedInstallTest/app/AndroidManifest.xml33
-rw-r--r--tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java135
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java111
-rw-r--r--tests/net/java/com/android/server/connectivity/DnsManagerTest.java50
-rw-r--r--tools/stats_log_api_gen/Android.bp1
-rw-r--r--tools/stats_log_api_gen/Collation.cpp11
-rw-r--r--tools/stats_log_api_gen/Collation.h4
-rw-r--r--tools/stats_log_api_gen/atoms_info_writer.cpp91
-rw-r--r--tools/stats_log_api_gen/atoms_info_writer.h35
-rw-r--r--tools/stats_log_api_gen/main.cpp61
-rw-r--r--tools/stats_log_api_gen/test.proto18
-rw-r--r--tools/stats_log_api_gen/test_collation.cpp19
-rw-r--r--tools/stats_log_api_gen/utils.h1
-rw-r--r--wifi/java/android/net/wifi/SoftApConfiguration.java27
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java23
537 files changed, 8816 insertions, 5231 deletions
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 483d2cc2ec57..9c1acafa800d 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -184,9 +184,8 @@ public class BlobStoreManager {
* @throws SecurityException when the caller is not allowed to create a session, such
* as when called from an Instant app.
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
- * @throws IllegalStateException when a new session could not be created, such as when the
- * caller is trying to create too many sessions or when the
- * device is running low on space.
+ * @throws LimitExceededException when a new session could not be created, such as when the
+ * caller is trying to create too many sessions.
*/
public @IntRange(from = 1) long createSession(@NonNull BlobHandle blobHandle)
throws IOException {
@@ -194,6 +193,7 @@ public class BlobStoreManager {
return mService.createSession(blobHandle, mContext.getOpPackageName());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
+ e.maybeRethrow(LimitExceededException.class);
throw new RuntimeException(e);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -302,8 +302,9 @@ public class BlobStoreManager {
* if the {@code leaseExpiryTimeMillis} is greater than the
* {@link BlobHandle#getExpiryTimeMillis()}.
* @throws LimitExceededException when a lease could not be acquired, such as when the
- * caller is trying to acquire leases on too much data. Apps
- * can avoid this by checking the remaining quota using
+ * caller is trying to acquire too many leases or acquire
+ * leases on too much data. Apps can avoid this by checking
+ * the remaining quota using
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
@@ -362,8 +363,9 @@ public class BlobStoreManager {
* if the {@code leaseExpiryTimeMillis} is greater than the
* {@link BlobHandle#getExpiryTimeMillis()}.
* @throws LimitExceededException when a lease could not be acquired, such as when the
- * caller is trying to acquire leases on too much data. Apps
- * can avoid this by checking the remaining quota using
+ * caller is trying to acquire too many leases or acquire
+ * leases on too much data. Apps can avoid this by checking
+ * the remaining quota using
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
@@ -415,8 +417,9 @@ public class BlobStoreManager {
* exist or the caller does not have access to it.
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
* @throws LimitExceededException when a lease could not be acquired, such as when the
- * caller is trying to acquire leases on too much data. Apps
- * can avoid this by checking the remaining quota using
+ * caller is trying to acquire too many leases or acquire
+ * leases on too much data. Apps can avoid this by checking
+ * the remaining quota using
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
@@ -462,8 +465,9 @@ public class BlobStoreManager {
* exist or the caller does not have access to it.
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
* @throws LimitExceededException when a lease could not be acquired, such as when the
- * caller is trying to acquire leases on too much data. Apps
- * can avoid this by checking the remaining quota using
+ * caller is trying to acquire too many leases or acquire
+ * leases on too much data. Apps can avoid this by checking
+ * the remaining quota using
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
@@ -757,6 +761,8 @@ public class BlobStoreManager {
* @throws SecurityException when the caller is not the owner of the session.
* @throws IllegalStateException when the caller tries to change access for a blob which is
* already committed.
+ * @throws LimitExceededException when the caller tries to explicitly allow too
+ * many packages using this API.
*/
public void allowPackageAccess(@NonNull String packageName, @NonNull byte[] certificate)
throws IOException {
@@ -764,6 +770,7 @@ public class BlobStoreManager {
mSession.allowPackageAccess(packageName, certificate);
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
+ e.maybeRethrow(LimitExceededException.class);
throw new RuntimeException(e);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
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 265479f7c533..79cd1b17a5b5 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
@@ -141,6 +141,36 @@ class BlobStoreConfig {
public static long DELETE_ON_LAST_LEASE_DELAY_MS =
DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS;
+ /**
+ * Denotes the maximum number of active sessions per app at any time.
+ */
+ public static final String KEY_MAX_ACTIVE_SESSIONS = "max_active_sessions";
+ public static int DEFAULT_MAX_ACTIVE_SESSIONS = 250;
+ public static int MAX_ACTIVE_SESSIONS = DEFAULT_MAX_ACTIVE_SESSIONS;
+
+ /**
+ * Denotes the maximum number of committed blobs per app at any time.
+ */
+ public static final String KEY_MAX_COMMITTED_BLOBS = "max_committed_blobs";
+ public static int DEFAULT_MAX_COMMITTED_BLOBS = 1000;
+ public static int MAX_COMMITTED_BLOBS = DEFAULT_MAX_COMMITTED_BLOBS;
+
+ /**
+ * Denotes the maximum number of leased blobs per app at any time.
+ */
+ public static final String KEY_MAX_LEASED_BLOBS = "max_leased_blobs";
+ public static int DEFAULT_MAX_LEASED_BLOBS = 500;
+ public static int MAX_LEASED_BLOBS = DEFAULT_MAX_LEASED_BLOBS;
+
+ /**
+ * Denotes the maximum number of packages explicitly permitted to access a blob
+ * (permitted as part of creating a {@link BlobAccessMode}).
+ */
+ public static final String KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES = "max_permitted_pks";
+ public static int DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES = 300;
+ public static int MAX_BLOB_ACCESS_PERMITTED_PACKAGES =
+ DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES;
+
static void refresh(Properties properties) {
if (!NAMESPACE_BLOBSTORE.equals(properties.getNamespace())) {
return;
@@ -178,6 +208,19 @@ class BlobStoreConfig {
DELETE_ON_LAST_LEASE_DELAY_MS = properties.getLong(key,
DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS);
break;
+ case KEY_MAX_ACTIVE_SESSIONS:
+ MAX_ACTIVE_SESSIONS = properties.getInt(key, DEFAULT_MAX_ACTIVE_SESSIONS);
+ break;
+ case KEY_MAX_COMMITTED_BLOBS:
+ MAX_COMMITTED_BLOBS = properties.getInt(key, DEFAULT_MAX_COMMITTED_BLOBS);
+ break;
+ case KEY_MAX_LEASED_BLOBS:
+ MAX_LEASED_BLOBS = properties.getInt(key, DEFAULT_MAX_LEASED_BLOBS);
+ break;
+ case KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES:
+ MAX_BLOB_ACCESS_PERMITTED_PACKAGES = properties.getInt(key,
+ DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES);
+ break;
default:
Slog.wtf(TAG, "Unknown key in device config properties: " + key);
}
@@ -210,6 +253,15 @@ class BlobStoreConfig {
fout.println(String.format(dumpFormat, KEY_DELETE_ON_LAST_LEASE_DELAY_MS,
TimeUtils.formatDuration(DELETE_ON_LAST_LEASE_DELAY_MS),
TimeUtils.formatDuration(DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS)));
+ fout.println(String.format(dumpFormat, KEY_MAX_ACTIVE_SESSIONS,
+ MAX_ACTIVE_SESSIONS, DEFAULT_MAX_ACTIVE_SESSIONS));
+ fout.println(String.format(dumpFormat, KEY_MAX_COMMITTED_BLOBS,
+ MAX_COMMITTED_BLOBS, DEFAULT_MAX_COMMITTED_BLOBS));
+ fout.println(String.format(dumpFormat, KEY_MAX_LEASED_BLOBS,
+ MAX_LEASED_BLOBS, DEFAULT_MAX_LEASED_BLOBS));
+ fout.println(String.format(dumpFormat, KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES,
+ MAX_BLOB_ACCESS_PERMITTED_PACKAGES,
+ DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES));
}
}
@@ -288,6 +340,34 @@ class BlobStoreConfig {
return DeviceConfigProperties.DELETE_ON_LAST_LEASE_DELAY_MS;
}
+ /**
+ * Returns the maximum number of active sessions per app.
+ */
+ public static int getMaxActiveSessions() {
+ return DeviceConfigProperties.MAX_ACTIVE_SESSIONS;
+ }
+
+ /**
+ * Returns the maximum number of committed blobs per app.
+ */
+ public static int getMaxCommittedBlobs() {
+ return DeviceConfigProperties.MAX_COMMITTED_BLOBS;
+ }
+
+ /**
+ * Returns the maximum number of leased blobs per app.
+ */
+ public static int getMaxLeasedBlobs() {
+ return DeviceConfigProperties.MAX_LEASED_BLOBS;
+ }
+
+ /**
+ * Returns the maximum number of packages explicitly permitted to access a blob.
+ */
+ public static int getMaxPermittedPackages() {
+ return DeviceConfigProperties.MAX_BLOB_ACCESS_PERMITTED_PACKAGES;
+ }
+
@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 a90536fee904..7a6c884848d8 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -35,6 +35,9 @@ import static com.android.server.blob.BlobStoreConfig.TAG;
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_CURRENT;
import static com.android.server.blob.BlobStoreConfig.getAdjustedCommitTimeMs;
import static com.android.server.blob.BlobStoreConfig.getDeletionOnLastLeaseDelayMs;
+import static com.android.server.blob.BlobStoreConfig.getMaxActiveSessions;
+import static com.android.server.blob.BlobStoreConfig.getMaxCommittedBlobs;
+import static com.android.server.blob.BlobStoreConfig.getMaxLeasedBlobs;
import static com.android.server.blob.BlobStoreSession.STATE_ABANDONED;
import static com.android.server.blob.BlobStoreSession.STATE_COMMITTED;
import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_INVALID;
@@ -124,6 +127,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -332,9 +336,26 @@ public class BlobStoreManagerService extends SystemService {
mKnownBlobIds.add(id);
}
+ @GuardedBy("mBlobsLock")
+ private int getSessionsCountLocked(int uid, String packageName) {
+ // TODO: Maintain a counter instead of traversing all the sessions
+ final AtomicInteger sessionsCount = new AtomicInteger(0);
+ forEachSessionInUser(session -> {
+ if (session.getOwnerUid() == uid && session.getOwnerPackageName().equals(packageName)) {
+ sessionsCount.getAndIncrement();
+ }
+ }, UserHandle.getUserId(uid));
+ return sessionsCount.get();
+ }
+
private long createSessionInternal(BlobHandle blobHandle,
int callingUid, String callingPackage) {
synchronized (mBlobsLock) {
+ final int sessionsCount = getSessionsCountLocked(callingUid, callingPackage);
+ if (sessionsCount >= getMaxActiveSessions()) {
+ throw new LimitExceededException("Too many active sessions for the caller: "
+ + sessionsCount);
+ }
// TODO: throw if there is already an active session associated with blobHandle.
final long sessionId = generateNextSessionIdLocked();
final BlobStoreSession session = new BlobStoreSession(mContext,
@@ -408,10 +429,39 @@ public class BlobStoreManagerService extends SystemService {
}
}
+ @GuardedBy("mBlobsLock")
+ private int getCommittedBlobsCountLocked(int uid, String packageName) {
+ // TODO: Maintain a counter instead of traversing all the blobs
+ final AtomicInteger blobsCount = new AtomicInteger(0);
+ forEachBlobInUser((blobMetadata) -> {
+ if (blobMetadata.isACommitter(packageName, uid)) {
+ blobsCount.getAndIncrement();
+ }
+ }, UserHandle.getUserId(uid));
+ return blobsCount.get();
+ }
+
+ @GuardedBy("mBlobsLock")
+ private int getLeasedBlobsCountLocked(int uid, String packageName) {
+ // TODO: Maintain a counter instead of traversing all the blobs
+ final AtomicInteger blobsCount = new AtomicInteger(0);
+ forEachBlobInUser((blobMetadata) -> {
+ if (blobMetadata.isALeasee(packageName, uid)) {
+ blobsCount.getAndIncrement();
+ }
+ }, UserHandle.getUserId(uid));
+ return blobsCount.get();
+ }
+
private void acquireLeaseInternal(BlobHandle blobHandle, int descriptionResId,
CharSequence description, long leaseExpiryTimeMillis,
int callingUid, String callingPackage) {
synchronized (mBlobsLock) {
+ final int leasesCount = getLeasedBlobsCountLocked(callingUid, callingPackage);
+ if (leasesCount >= getMaxLeasedBlobs()) {
+ throw new LimitExceededException("Too many leased blobs for the caller: "
+ + leasesCount);
+ }
final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
@@ -626,6 +676,18 @@ public class BlobStoreManagerService extends SystemService {
break;
case STATE_VERIFIED_VALID:
synchronized (mBlobsLock) {
+ final int committedBlobsCount = getCommittedBlobsCountLocked(
+ session.getOwnerUid(), session.getOwnerPackageName());
+ if (committedBlobsCount >= getMaxCommittedBlobs()) {
+ Slog.d(TAG, "Failed to commit: too many committed blobs. count: "
+ + committedBlobsCount + "; blob: " + session);
+ session.sendCommitCallbackResult(COMMIT_RESULT_ERROR);
+ session.getSessionFile().delete();
+ mActiveBlobIds.remove(session.getSessionId());
+ getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
+ .remove(session.getSessionId());
+ break;
+ }
final int userId = UserHandle.getUserId(session.getOwnerUid());
final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(
userId);
@@ -656,7 +718,7 @@ public class BlobStoreManagerService extends SystemService {
} else {
blob.addOrReplaceCommitter(existingCommitter);
}
- Slog.d(TAG, "Error committing the blob", e);
+ Slog.d(TAG, "Error committing the blob: " + session, e);
FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED,
session.getOwnerUid(), blob.getBlobId(), blob.getSize(),
FrameworkStatsLog.BLOB_COMMITTED__RESULT__ERROR_DURING_COMMIT);
@@ -1096,6 +1158,16 @@ public class BlobStoreManagerService extends SystemService {
void runClearAllSessions(@UserIdInt int userId) {
synchronized (mBlobsLock) {
+ for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
+ final int sessionUserId = mSessions.keyAt(i);
+ if (userId != UserHandle.USER_ALL && userId != sessionUserId) {
+ continue;
+ }
+ final LongSparseArray<BlobStoreSession> userSessions = mSessions.valueAt(i);
+ for (int j = 0, sessionsCount = userSessions.size(); j < sessionsCount; ++j) {
+ mActiveBlobIds.remove(userSessions.valueAt(j).getSessionId());
+ }
+ }
if (userId == UserHandle.USER_ALL) {
mSessions.clear();
} else {
@@ -1107,6 +1179,16 @@ public class BlobStoreManagerService extends SystemService {
void runClearAllBlobs(@UserIdInt int userId) {
synchronized (mBlobsLock) {
+ for (int i = 0, userCount = mBlobsMap.size(); i < userCount; ++i) {
+ final int blobUserId = mBlobsMap.keyAt(i);
+ if (userId != UserHandle.USER_ALL && userId != blobUserId) {
+ continue;
+ }
+ final ArrayMap<BlobHandle, BlobMetadata> userBlobs = mBlobsMap.valueAt(i);
+ for (int j = 0, blobsCount = userBlobs.size(); j < blobsCount; ++j) {
+ mActiveBlobIds.remove(userBlobs.valueAt(j).getBlobId());
+ }
+ }
if (userId == UserHandle.USER_ALL) {
mBlobsMap.clear();
} else {
@@ -1331,8 +1413,11 @@ public class BlobStoreManagerService extends SystemService {
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
}
- // TODO: Verify caller request is within limits (no. of calls/blob sessions/blobs)
- return createSessionInternal(blobHandle, callingUid, packageName);
+ try {
+ return createSessionInternal(blobHandle, callingUid, packageName);
+ } catch (LimitExceededException e) {
+ throw new ParcelableException(e);
+ }
}
@Override
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 baafff53d072..53e296ba3d11 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -32,6 +32,7 @@ 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;
+import static com.android.server.blob.BlobStoreConfig.getMaxPermittedPackages;
import static com.android.server.blob.BlobStoreConfig.hasSessionExpired;
import android.annotation.BytesLong;
@@ -43,7 +44,9 @@ import android.app.blob.IBlobStoreSession;
import android.content.Context;
import android.os.Binder;
import android.os.FileUtils;
+import android.os.LimitExceededException;
import android.os.ParcelFileDescriptor;
+import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
import android.os.Trace;
@@ -76,7 +79,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
-/** TODO: add doc */
+/**
+ * Class to represent the state corresponding to an ongoing
+ * {@link android.app.blob.BlobStoreManager.Session}
+ */
@VisibleForTesting
class BlobStoreSession extends IBlobStoreSession.Stub {
@@ -326,6 +332,11 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
throw new IllegalStateException("Not allowed to change access type in state: "
+ stateToString(mState));
}
+ if (mBlobAccessMode.getNumWhitelistedPackages() >= getMaxPermittedPackages()) {
+ throw new ParcelableException(new LimitExceededException(
+ "Too many packages permitted to access the blob: "
+ + mBlobAccessMode.getNumWhitelistedPackages()));
+ }
mBlobAccessMode.allowPackageAccess(packageName, certificate);
}
}
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 8a3fbde5609b..71cc044d0cec 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -841,6 +841,35 @@ public final class MediaParser {
*/
public static final String PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT =
"android.media.mediaParser.exposeChunkIndexAsMediaFormat";
+ /**
+ * Sets a list of closed-caption {@link MediaFormat MediaFormats} that should be exposed as part
+ * of the extracted media. {@code List<MediaFormat>} expected. Default value is an empty list.
+ *
+ * <p>Expected keys in the {@link MediaFormat} are:
+ *
+ * <ul>
+ * <p>{@link MediaFormat#KEY_MIME}: Determine the type of captions (for example,
+ * application/cea-608). Mandatory.
+ * <p>{@link MediaFormat#KEY_CAPTION_SERVICE_NUMBER}: Determine the channel on which the
+ * captions are transmitted. Optional.
+ * </ul>
+ *
+ * @hide
+ */
+ public static final String PARAMETER_EXPOSE_CAPTION_FORMATS =
+ "android.media.mediaParser.exposeCaptionFormats";
+ /**
+ * Sets whether the value associated with {@link #PARAMETER_EXPOSE_CAPTION_FORMATS} should
+ * override any in-band caption service declarations. {@code boolean} expected. Default value is
+ * {@link false}.
+ *
+ * <p>When {@code false}, any present in-band caption services information will override the
+ * values associated with {@link #PARAMETER_EXPOSE_CAPTION_FORMATS}.
+ *
+ * @hide
+ */
+ public static final String PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS =
+ "android.media.mediaParser.overrideInBandCaptionDeclarations";
// Private constants.
@@ -851,6 +880,7 @@ public final class MediaParser {
private static final String TS_MODE_MULTI_PMT = "multi_pmt";
private static final String TS_MODE_HLS = "hls";
private static final int BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY = 6;
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
@IntDef(
value = {
@@ -1000,6 +1030,7 @@ public final class MediaParser {
private final DataReaderAdapter mScratchDataReaderAdapter;
private final ParsableByteArrayAdapter mScratchParsableByteArrayAdapter;
@Nullable private final Constructor<DrmInitData.SchemeInitData> mSchemeInitDataConstructor;
+ private final ArrayList<Format> mMuxedCaptionFormats;
private boolean mInBandCryptoInfo;
private boolean mIncludeSupplementalData;
private boolean mIgnoreTimestampOffset;
@@ -1071,6 +1102,9 @@ public final class MediaParser {
if (PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT.equals(parameterName)) {
mExposeChunkIndexAsMediaFormat = (boolean) value;
}
+ if (PARAMETER_EXPOSE_CAPTION_FORMATS.equals(parameterName)) {
+ setMuxedCaptionFormats((List<MediaFormat>) value);
+ }
mParserParameters.put(parameterName, value);
return this;
}
@@ -1109,8 +1143,8 @@ public final class MediaParser {
*
* <p>This method will block until some progress has been made.
*
- * <p>If this instance was created using {@link #create}. the first call to this method will
- * sniff the content with the parsers with the provided names.
+ * <p>If this instance was created using {@link #create}, the first call to this method will
+ * sniff the content using the selected parser implementations.
*
* @param seekableInputReader The {@link SeekableInputReader} from which to obtain the media
* container data.
@@ -1242,6 +1276,14 @@ public final class MediaParser {
mScratchDataReaderAdapter = new DataReaderAdapter();
mScratchParsableByteArrayAdapter = new ParsableByteArrayAdapter();
mSchemeInitDataConstructor = getSchemeInitDataConstructor();
+ mMuxedCaptionFormats = new ArrayList<>();
+ }
+
+ private void setMuxedCaptionFormats(List<MediaFormat> mediaFormats) {
+ mMuxedCaptionFormats.clear();
+ for (MediaFormat mediaFormat : mediaFormats) {
+ mMuxedCaptionFormats.add(toExoPlayerCaptionFormat(mediaFormat));
+ }
}
private boolean isPendingSeek() {
@@ -1280,7 +1322,11 @@ public final class MediaParser {
? FragmentedMp4Extractor
.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
: 0;
- return new FragmentedMp4Extractor(flags, timestampAdjuster);
+ return new FragmentedMp4Extractor(
+ flags,
+ timestampAdjuster,
+ /* sideloadedTrack= */ null,
+ mMuxedCaptionFormats);
case PARSER_NAME_MP4:
flags |=
getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
@@ -1331,6 +1377,10 @@ public final class MediaParser {
getBooleanParameter(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM)
? DefaultTsPayloadReaderFactory.FLAG_IGNORE_SPLICE_INFO_STREAM
: 0;
+ flags |=
+ getBooleanParameter(PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS)
+ ? DefaultTsPayloadReaderFactory.FLAG_OVERRIDE_CAPTION_DESCRIPTORS
+ : 0;
String tsMode = getStringParameter(PARAMETER_TS_MODE, TS_MODE_SINGLE_PMT);
int hlsMode =
TS_MODE_SINGLE_PMT.equals(tsMode)
@@ -1343,7 +1393,7 @@ public final class MediaParser {
timestampAdjuster != null
? timestampAdjuster
: new TimestampAdjuster(/* firstSampleTimestampUs= */ 0),
- new DefaultTsPayloadReaderFactory(flags));
+ new DefaultTsPayloadReaderFactory(flags, mMuxedCaptionFormats));
case PARSER_NAME_FLV:
return new FlvExtractor();
case PARSER_NAME_OGG:
@@ -1625,6 +1675,9 @@ public final class MediaParser {
if (cryptoData != mLastReceivedCryptoData) {
mLastOutputCryptoInfo =
createNewCryptoInfoAndPopulateWithCryptoData(cryptoData);
+ // We are using in-band crypto info, so the IV will be ignored. But we prevent
+ // it from being null because toString assumes it non-null.
+ mLastOutputCryptoInfo.iv = EMPTY_BYTE_ARRAY;
}
} else /* We must populate the full CryptoInfo. */ {
// CryptoInfo.pattern is not accessible to the user, so the user needs to feed
@@ -1789,6 +1842,16 @@ public final class MediaParser {
// Private static methods.
+ private static Format toExoPlayerCaptionFormat(MediaFormat mediaFormat) {
+ Format.Builder formatBuilder =
+ new Format.Builder().setSampleMimeType(mediaFormat.getString(MediaFormat.KEY_MIME));
+ if (mediaFormat.containsKey(MediaFormat.KEY_CAPTION_SERVICE_NUMBER)) {
+ formatBuilder.setAccessibilityChannel(
+ mediaFormat.getInteger(MediaFormat.KEY_CAPTION_SERVICE_NUMBER));
+ }
+ return formatBuilder.build();
+ }
+
private static MediaFormat toMediaFormat(Format format) {
MediaFormat result = new MediaFormat();
setOptionalMediaFormatInt(result, MediaFormat.KEY_BIT_RATE, format.bitrate);
@@ -1857,8 +1920,10 @@ public final class MediaParser {
// format for convenient use from ExoPlayer.
result.setString("crypto-mode-fourcc", format.drmInitData.schemeType);
}
+ if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
+ result.setLong("subsample-offset-us-long", format.subsampleOffsetUs);
+ }
// LACK OF SUPPORT FOR:
- // format.containerMimeType;
// format.id;
// format.metadata;
// format.stereoMode;
@@ -2041,6 +2106,11 @@ public final class MediaParser {
expectedTypeByParameterName.put(PARAMETER_EXPOSE_DUMMY_SEEKMAP, Boolean.class);
expectedTypeByParameterName.put(
PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT, Boolean.class);
+ expectedTypeByParameterName.put(
+ PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS, Boolean.class);
+ // We do not check PARAMETER_EXPOSE_CAPTION_FORMATS here, and we do it in setParameters
+ // instead. Checking that the value is a List is insufficient to catch wrong parameter
+ // value types.
EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
}
}
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 8a0f66040711..d19faa97e223 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -74,6 +74,7 @@ java_sdk_library {
visibility: [
"//frameworks/base", // Framework
"//frameworks/base/apex/statsd:__subpackages__", // statsd apex
+ "//frameworks/base/packages/Tethering", // Tethering
"//frameworks/opt/net/wifi/service", // wifi service
"//packages/providers/MediaProvider", // MediaProvider apk
],
@@ -88,4 +89,4 @@ java_sdk_library {
"com.android.os.statsd",
"test_com.android.os.statsd",
],
-} \ No newline at end of file
+}
diff --git a/api/test-current.txt b/api/test-current.txt
index fc82bc788ac7..7fd56984799f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -32,6 +32,7 @@ package android {
}
public static final class R.bool {
+ field public static final int config_assistantOnTopOfDream = 17891333; // 0x1110005
field public static final int config_perDisplayFocusEnabled = 17891332; // 0x1110004
}
@@ -5263,6 +5264,7 @@ package android.view.autofill {
ctor public AutofillId(int, int);
ctor public AutofillId(@NonNull android.view.autofill.AutofillId, long, int);
method public boolean equalsIgnoreSession(@Nullable android.view.autofill.AutofillId);
+ method @NonNull public static android.view.autofill.AutofillId withoutSession(@NonNull android.view.autofill.AutofillId);
}
public final class AutofillManager {
@@ -5504,6 +5506,19 @@ package android.widget {
}
+package android.widget.inline {
+
+ public class InlineContentView extends android.view.ViewGroup {
+ method public void setChildSurfacePackageUpdater(@Nullable android.widget.inline.InlineContentView.SurfacePackageUpdater);
+ }
+
+ public static interface InlineContentView.SurfacePackageUpdater {
+ method public void getSurfacePackage(@NonNull java.util.function.Consumer<android.view.SurfaceControlViewHost.SurfacePackage>);
+ method public void onSurfacePackageReleased();
+ }
+
+}
+
package android.window {
public final class DisplayAreaInfo implements android.os.Parcelable {
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 3dbe41395024..0617eb6c0e66 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -116,7 +116,6 @@ cc_defaults {
"libcutils",
"libgtest_prod",
"libprotoutil",
- "libstatsmetadata",
"libstatslog_statsd",
"libsysutils",
"libutils",
@@ -129,51 +128,6 @@ cc_defaults {
],
}
-// ================
-// libstatsmetadata
-// ================
-
-genrule {
- name: "atoms_info.h",
- tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --atomsInfoHeader $(genDir)/atoms_info.h",
- out: [
- "atoms_info.h",
- ],
-}
-
-genrule {
- name: "atoms_info.cpp",
- tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --atomsInfoCpp $(genDir)/atoms_info.cpp",
- out: [
- "atoms_info.cpp",
- ],
-}
-
-cc_library_static {
- name: "libstatsmetadata",
- host_supported: true,
- generated_sources: [
- "atoms_info.cpp",
- ],
- generated_headers: [
- "atoms_info.h",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- export_generated_headers: [
- "atoms_info.h",
- ],
- apex_available: [
- //TODO(b/149782403): Remove this once statsd no longer links against libstatsmetadata
- "com.android.os.statsd",
- "test_com.android.os.statsd",
- ],
-}
-
genrule {
name: "statslog_statsd.h",
tools: ["stats-log-api-gen"],
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 8527185d3891..ff5717e4fa78 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -110,8 +110,6 @@ extend google.protobuf.FieldOptions {
optional LogMode log_mode = 50002 [default = MODE_AUTOMATIC];
- optional bool allow_from_any_uid = 50003 [default = false];
-
repeated string module = 50004;
optional bool truncate_timestamp = 50005 [default = false];
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index dc20a02156cb..ca03343ddb80 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -145,8 +145,7 @@ message Atom {
PacketWakeupOccurred packet_wakeup_occurred = 44 [(module) = "framework"];
WallClockTimeShifted wall_clock_time_shifted = 45 [(module) = "framework"];
AnomalyDetected anomaly_detected = 46 [(module) = "statsd"];
- AppBreadcrumbReported app_breadcrumb_reported =
- 47 [(allow_from_any_uid) = true, (module) = "statsd"];
+ AppBreadcrumbReported app_breadcrumb_reported = 47 [(module) = "statsd"];
AppStartOccurred app_start_occurred = 48 [(module) = "framework", (module) = "statsdtest"];
AppStartCanceled app_start_canceled = 49 [(module) = "framework"];
AppStartFullyDrawn app_start_fully_drawn = 50 [(module) = "framework"];
@@ -157,7 +156,7 @@ message Atom {
AppStartMemoryStateCaptured app_start_memory_state_captured = 55 [(module) = "framework"];
ShutdownSequenceReported shutdown_sequence_reported = 56 [(module) = "framework"];
BootSequenceReported boot_sequence_reported = 57;
- DaveyOccurred davey_occurred = 58 [(allow_from_any_uid) = true, (module) = "statsd"];
+ DaveyOccurred davey_occurred = 58 [(module) = "statsd"];
OverlayStateChanged overlay_state_changed =
59 [(module) = "framework", (module) = "statsdtest"];
ForegroundServiceStateChanged foreground_service_state_changed
@@ -186,8 +185,7 @@ message Atom {
WTFOccurred wtf_occurred = 80 [(module) = "framework"];
LowMemReported low_mem_reported = 81 [(module) = "framework"];
GenericAtom generic_atom = 82;
- KeyValuePairsAtom key_value_pairs_atom =
- 83 [(allow_from_any_uid) = true, (module) = "framework", (module) = "statsd"];
+ KeyValuePairsAtom key_value_pairs_atom = 83 [(module) = "framework", (module) = "statsd"];
VibratorStateChanged vibrator_state_changed = 84 [(module) = "framework"];
DeferredJobStatsReported deferred_job_stats_reported = 85 [(module) = "framework"];
ThermalThrottlingStateChanged thermal_throttling = 86 [deprecated=true];
@@ -317,7 +315,7 @@ message Atom {
AssistGestureFeedbackReported assist_gesture_feedback_reported = 175 [(module) = "sysui"];
AssistGestureProgressReported assist_gesture_progress_reported = 176 [(module) = "sysui"];
TouchGestureClassified touch_gesture_classified = 177 [(module) = "framework"];
- HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true, (module) = "framework"];
+ HiddenApiUsed hidden_api_used = 178 [(module) = "framework"];
StyleUIChanged style_ui_changed = 179 [(module) = "sysui"];
PrivacyIndicatorsInteracted privacy_indicators_interacted =
180 [(module) = "permissioncontroller"];
@@ -383,7 +381,7 @@ message Atom {
UpdateEngineSuccessfulUpdateReported update_engine_successful_update_reported = 226;
CameraActionEvent camera_action_event = 227 [(module) = "framework"];
AppCompatibilityChangeReported app_compatibility_change_reported =
- 228 [(allow_from_any_uid) = true, (module) = "framework"];
+ 228 [(module) = "framework"];
PerfettoUploaded perfetto_uploaded = 229 [(module) = "perfetto"];
VmsClientConnectionStateChanged vms_client_connection_state_changed =
230 [(module) = "car"];
@@ -486,6 +484,7 @@ message Atom {
KeystoreKeyEventReported keystore_key_event_reported = 302;
NetworkTetheringReported network_tethering_reported =
303 [(module) = "network_tethering"];
+ ImeTouchReported ime_touch_reported = 304 [(module) = "sysui"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
@@ -3061,6 +3060,18 @@ message ExclusionRectStateChanged {
}
/**
+ * Logs when IME is on.
+ *
+ * Logged from: /packages/SystemUI/src/com/android/systemui/
+ statusbar/phone/NavigationBarView.java
+ *
+ */
+message ImeTouchReported {
+ optional int32 x_coordinate = 1; // X coordinate for ACTION_DOWN event.
+ optional int32 y_coordinate = 2; // Y coordinate for ACTION_DOWN event.
+}
+
+/**
* Logs when Launcher (HomeScreen) UI has changed or was interacted.
*
* Logged from:
@@ -6120,6 +6131,10 @@ message ProcessStatsAvailablePagesProto {
*/
message ProcStats {
optional ProcessStatsSectionProto proc_stats_section = 1;
+ // Data pulled from device into this is sometimes sharded across multiple atoms to work around
+ // a size limit. When this happens, this shard ID will contain an increasing 1-indexed integer
+ // with the number of this shard.
+ optional int32 shard_id = 2;
}
/**
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 7e825efddb75..60de1a24cce5 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -21,7 +21,6 @@
#include <private/android_filesystem_config.h>
#include "CountMetricProducer.h"
-#include "atoms_info.h"
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "guardrail/StatsdStats.h"
@@ -372,13 +371,6 @@ void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
bool MetricsManager::checkLogCredentials(const LogEvent& event) {
- // TODO(b/154856835): Remove this check once we get whitelist from the config.
- if (android::util::AtomsInfo::kWhitelistedAtoms.find(event.GetTagId()) !=
- android::util::AtomsInfo::kWhitelistedAtoms.end())
- {
- return true;
- }
-
if (mWhitelistedAtomIds.find(event.GetTagId()) != mWhitelistedAtomIds.end()) {
return true;
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 22a63d9b486b..3772755beca1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2816,6 +2816,11 @@ public class Activity extends ContextThemeWrapper
* The system may disallow entering picture-in-picture in various cases, including when the
* activity is not visible, if the screen is locked or if the user has an activity pinned.
*
+ * <p>By default, system calculates the dimension of picture-in-picture window based on the
+ * given {@param params}.
+ * See <a href="{@docRoot}guide/topics/ui/picture-in-picture">Picture-in-picture Support</a>
+ * on how to override this behavior.</p>
+ *
* @see android.R.attr#supportsPictureInPicture
* @see PictureInPictureParams
*
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index b749c3504811..98a23f2b0075 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -33,7 +33,10 @@ import android.hardware.display.VirtualDisplay;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.Display;
+import android.view.DisplayInfo;
import android.view.IWindow;
import android.view.IWindowManager;
import android.view.KeyEvent;
@@ -407,6 +410,9 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
}
private class SurfaceCallback implements SurfaceHolder.Callback {
+ private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
+ private final DisplayMetrics mTempMetrics = new DisplayMetrics();
+
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (!mTaskEmbedder.isInitialized()) {
@@ -415,13 +421,21 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
mTmpTransaction.reparent(mTaskEmbedder.getSurfaceControl(),
mSurfaceView.getSurfaceControl()).apply();
}
+ mTaskEmbedder.resizeTask(getWidth(), getHeight());
mTaskEmbedder.start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
- mTaskEmbedder.resizeTask(width, height);
- mTaskEmbedder.notifyBoundsChanged();
+ final Display display = getVirtualDisplay().getDisplay();
+ if (!display.getDisplayInfo(mTempDisplayInfo)) {
+ return;
+ }
+ mTempDisplayInfo.getAppMetrics(mTempMetrics);
+ if (width != mTempMetrics.widthPixels || height != mTempMetrics.heightPixels) {
+ mTaskEmbedder.resizeTask(width, height);
+ mTaskEmbedder.notifyBoundsChanged();
+ }
}
@Override
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 3347e045886a..0a6827cde3d3 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -7370,15 +7370,17 @@ public class AppOpsManager {
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
+ boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID ? true : false;
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
// Set stack trace as default message
message = getFormattedStackTrace();
+ shouldCollectMessage = true;
}
}
int mode = mService.noteOperation(op, uid, packageName, attributionTag,
- collectionMode == COLLECT_ASYNC, message);
+ collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
@@ -7531,16 +7533,19 @@ public class AppOpsManager {
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, op);
+ boolean shouldCollectMessage = myUid == Process.SYSTEM_UID ? true : false;
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
// Set stack trace as default message
message = getFormattedStackTrace();
+ shouldCollectMessage = true;
}
}
int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
proxiedAttributionTag, myUid, mContext.getOpPackageName(),
- mContext.getAttributionTag(), collectionMode == COLLECT_ASYNC, message);
+ mContext.getAttributionTag(), collectionMode == COLLECT_ASYNC, message,
+ shouldCollectMessage);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
@@ -7855,15 +7860,18 @@ public class AppOpsManager {
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
+ boolean shouldCollectMessage = Process.myUid() == Process.SYSTEM_UID ? true : false;
if (collectionMode == COLLECT_ASYNC) {
if (message == null) {
// Set stack trace as default message
message = getFormattedStackTrace();
+ shouldCollectMessage = true;
}
}
int mode = mService.startOperation(getClientId(), op, uid, packageName,
- attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message);
+ attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message,
+ shouldCollectMessage);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 309e91f1e4ff..5e032f00a3a0 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -22,7 +22,7 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.app.IAppOpsCallback;
-import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.QuadFunction;
/**
@@ -73,9 +73,9 @@ public abstract class AppOpsManagerInternal {
*/
int noteOperation(int code, int uid, @Nullable String packageName,
@Nullable String featureId, boolean shouldCollectAsyncNotedOp,
- @Nullable String message,
- @NonNull HexFunction<Integer, Integer, String, String, Boolean, String, Integer>
- superImpl);
+ @Nullable String message, boolean shouldCollectMessage,
+ @NonNull HeptFunction<Integer, Integer, String, String, Boolean, String, Boolean,
+ Integer> superImpl);
}
/**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 6f8233d5de9b..c9031b711657 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -763,26 +763,27 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public void revokeRuntimePermission(String packageName, String permName, UserHandle user) {
+ revokeRuntimePermission(packageName, permName, user, null);
+ }
+
+ @Override
+ public void revokeRuntimePermission(String packageName, String permName, UserHandle user,
+ String reason) {
if (DEBUG_TRACE_PERMISSION_UPDATES
&& shouldTraceGrant(packageName, permName, user.getIdentifier())) {
Log.i(TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
- + permName + " for user " + user.getIdentifier(), new RuntimeException());
+ + permName + " for user " + user.getIdentifier() + " with reason " + reason,
+ new RuntimeException());
}
try {
mPermissionManager
- .revokeRuntimePermission(packageName, permName, user.getIdentifier());
+ .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@Override
- public void revokeRuntimePermission(String packageName, String permName, UserHandle user,
- String reason) {
- // TODO evanseverson: impl
- }
-
- @Override
public int getPermissionFlags(String permName, String packageName, UserHandle user) {
try {
return mPermissionManager
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 86a3579effe1..a828aac78ded 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1900,11 +1900,13 @@ class ContextImpl extends Context {
@Override
public Object getSystemService(String name) {
+ // We may override this API from outer context.
+ final boolean isUiContext = isUiContext() || getOuterContext().isUiContext();
// Check incorrect Context usage.
- if (isUiComponent(name) && !isUiContext() && vmIncorrectContextUseEnabled()) {
+ if (isUiComponent(name) && !isUiContext && vmIncorrectContextUseEnabled()) {
final String errorMessage = "Tried to access visual service "
+ SystemServiceRegistry.getSystemServiceClassName(name)
- + " from a non-visual Context. ";
+ + " from a non-visual Context:" + getOuterContext();
final String message = "Visual services, such as WindowManager, WallpaperService or "
+ "LayoutInflater should be accessed from Activity or other visual Context. "
+ "Use an Activity or a Context created with "
@@ -2369,6 +2371,7 @@ class ContextImpl extends Context {
context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo(),
mResources.getLoaders()));
+ context.mIsUiContext = isUiContext() || getOuterContext().isUiContext();
return context;
}
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 1278ff6817fd..0719422632d1 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -25,6 +25,7 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ClipDescription;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -50,11 +51,13 @@ import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.LongSparseArray;
import android.util.Pair;
+import android.webkit.MimeTypeMap;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
/**
* The download manager is a system service that handles long-running HTTP downloads. Clients may
@@ -1554,6 +1557,7 @@ public class DownloadManager {
values.put(Downloads.Impl.COLUMN_DESTINATION,
Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD);
values.put(Downloads.Impl._DATA, path);
+ values.put(Downloads.Impl.COLUMN_MIME_TYPE, resolveMimeType(new File(path)));
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_SUCCESS);
values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, length);
values.put(Downloads.Impl.COLUMN_MEDIA_SCANNED,
@@ -1569,6 +1573,58 @@ public class DownloadManager {
return Long.parseLong(downloadUri.getLastPathSegment());
}
+ /**
+ * Shamelessly borrowed from
+ * {@code packages/providers/MediaProvider/src/com/android/providers/media/util/MimeUtils.java}
+ *
+ * @hide
+ */
+ private static @NonNull String resolveMimeType(@NonNull File file) {
+ final String extension = extractFileExtension(file.getPath());
+ if (extension == null) return ClipDescription.MIMETYPE_UNKNOWN;
+
+ final String mimeType = MimeTypeMap.getSingleton()
+ .getMimeTypeFromExtension(extension.toLowerCase(Locale.ROOT));
+ if (mimeType == null) return ClipDescription.MIMETYPE_UNKNOWN;
+
+ return mimeType;
+ }
+
+ /**
+ * Shamelessly borrowed from
+ * {@code packages/providers/MediaProvider/src/com/android/providers/media/util/FileUtils.java}
+ *
+ * @hide
+ */
+ private static @Nullable String extractDisplayName(@Nullable String data) {
+ if (data == null) return null;
+ if (data.indexOf('/') == -1) {
+ return data;
+ }
+ if (data.endsWith("/")) {
+ data = data.substring(0, data.length() - 1);
+ }
+ return data.substring(data.lastIndexOf('/') + 1);
+ }
+
+ /**
+ * Shamelessly borrowed from
+ * {@code packages/providers/MediaProvider/src/com/android/providers/media/util/FileUtils.java}
+ *
+ * @hide
+ */
+ private static @Nullable String extractFileExtension(@Nullable String data) {
+ if (data == null) return null;
+ data = extractDisplayName(data);
+
+ final int lastDot = data.lastIndexOf('.');
+ if (lastDot == -1) {
+ return null;
+ } else {
+ return data.substring(lastDot + 1);
+ }
+ }
+
private static final String NON_DOWNLOADMANAGER_DOWNLOAD =
"non-dwnldmngr-download-dont-retry2download";
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index e84c5e574713..945957738f8e 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -677,4 +677,10 @@ interface IActivityManager {
* Return whether the app freezer is supported (true) or not (false) by this system.
*/
boolean isAppFreezerSupported();
+
+
+ /**
+ * Kills uid with the reason of permission change.
+ */
+ void killUidForPermissionChange(int appId, int userId, String reason);
}
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 82e988109db8..ce51dba76780 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -294,7 +294,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
final long identity = Binder.clearCallingIdentity();
try {
- mPermissionManager.revokeRuntimePermission(packageName, permission, userId);
+ mPermissionManager.revokeRuntimePermission(packageName, permission, userId, null);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index d6e77624a967..fc8248e1012a 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -41,6 +41,7 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.telephony.TelephonyManager;
import android.util.DataUnit;
import android.util.Log;
@@ -198,6 +199,12 @@ public class NetworkStatsManager {
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
* etc.
* @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when querying for the mobile network type to receive usage
+ * for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -231,6 +238,12 @@ public class NetworkStatsManager {
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
* etc.
* @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when querying for the mobile network type to receive usage
+ * for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -268,6 +281,12 @@ public class NetworkStatsManager {
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
* etc.
* @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when querying for the mobile network type to receive usage
+ * for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -301,7 +320,7 @@ public class NetworkStatsManager {
/**
* Query network usage statistics details for a given uid.
*
- * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
+ * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
*/
public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
long startTime, long endTime, int uid) throws SecurityException {
@@ -319,7 +338,7 @@ public class NetworkStatsManager {
/**
* Query network usage statistics details for a given uid and tag.
*
- * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
+ * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
*/
public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
long startTime, long endTime, int uid, int tag) throws SecurityException {
@@ -344,6 +363,12 @@ public class NetworkStatsManager {
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
* etc.
* @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when querying for the mobile network type to receive usage
+ * for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -398,6 +423,12 @@ public class NetworkStatsManager {
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
* etc.
* @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when querying for the mobile network type to receive usage
+ * for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
* @param startTime Start of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
@@ -455,7 +486,7 @@ public class NetworkStatsManager {
/**
* Registers to receive notifications about data usage on specified networks.
*
- * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
+ * @see #registerUsageCallback(int, String, long, UsageCallback, Handler)
*/
public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
UsageCallback callback) {
@@ -472,6 +503,12 @@ public class NetworkStatsManager {
* @param networkType Type of network to monitor. Either
{@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
* @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when registering for the mobile network type to receive
+ * notifications for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
* @param thresholdBytes Threshold in bytes to be notified on.
* @param callback The {@link UsageCallback} that the system will call when data usage
* has exceeded the specified threshold.
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 2ce6a86753a6..8a6cc95319fb 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -154,6 +154,7 @@ public final class UsageStatsManager {
* been misbehaving in some manner.
* Apps in this bucket will have the most restrictions, including network restrictions and
* additional restrictions on jobs.
+ * <p> Note: this bucket is not enabled in {@link Build.VERSION_CODES#R}.
* @see #getAppStandbyBucket()
*/
public static final int STANDBY_BUCKET_RESTRICTED = 45;
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 30ee32604939..15625cdeb8f4 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -680,7 +680,7 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
- *<p>Devices capable of streaming concurrently with other devices as described by
+ *<p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as described by
* {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
* following guaranteed streams (when streaming concurrently with other devices)</p>
*
@@ -696,10 +696,14 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <p> Devices which are not backwards-compatible, support a mandatory single stream of size sVGA with image format {@code DEPTH16} during concurrent operation.
+ *
* <p> For guaranteed concurrent stream configurations:</p>
- * <p> s720p refers to the camera device's resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
+ * <p> sVGA refers to the camera device's maximum resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
+ * VGA resolution (640X480) whichever is lower. </p>
+ * <p> s720p refers to the camera device's maximum resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
* 720p(1280X720) whichever is lower. </p>
- * <p> s1440p refers to the camera device's resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
+ * <p> s1440p refers to the camera device's maximum resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
* 1440p(1920X1440) whichever is lower. </p>
* <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
* includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices
@@ -707,6 +711,7 @@ public abstract class CameraDevice implements AutoCloseable {
* streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level
* and capabilities.</p>
*
+ *
* <p>Devices capable of outputting HEIC formats ({@link StreamConfigurationMap#getOutputFormats}
* contains {@link android.graphics.ImageFormat#HEIC}) will support substituting {@code JPEG}
* streams with {@code HEIC} in all guaranteed stream combinations for the device's hardware
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 20d9c30bb4cc..776d155e5b3e 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -685,6 +685,12 @@ public final class MandatoryStreamCombination {
"Standard still image capture"),
};
+ private static StreamCombinationTemplate sConcurrentDepthOnlyStreamCombinations[] = {
+ new StreamCombinationTemplate(new StreamTemplate [] {
+ new StreamTemplate(ImageFormat.DEPTH16, SizeThreshold.VGA) },
+ "Depth capture for mesh based object rendering"),
+ };
+
/**
* Helper builder class to generate a list of available mandatory stream combinations.
* @hide
@@ -729,19 +735,21 @@ public final class MandatoryStreamCombination {
getAvailableMandatoryConcurrentStreamCombinations() {
// Since concurrent streaming support is optional, we mandate these stream
// combinations regardless of camera device capabilities.
+
+ StreamCombinationTemplate []chosenStreamCombinations = sConcurrentStreamCombinations;
if (!isColorOutputSupported()) {
- Log.v(TAG, "Device is not backward compatible!");
- throw new IllegalArgumentException("Camera device which is not BACKWARD_COMPATIBLE"
- + " cannot have mandatory concurrent streams");
+ Log.v(TAG, "Device is not backward compatible, depth streams are mandatory!");
+ chosenStreamCombinations = sConcurrentDepthOnlyStreamCombinations;
}
+ Size sizeVGAp = new Size(640, 480);
Size size720p = new Size(1280, 720);
Size size1440p = new Size(1920, 1440);
ArrayList<MandatoryStreamCombination> availableConcurrentStreamCombinations =
new ArrayList<MandatoryStreamCombination>();
availableConcurrentStreamCombinations.ensureCapacity(
- sConcurrentStreamCombinations.length);
- for (StreamCombinationTemplate combTemplate : sConcurrentStreamCombinations) {
+ chosenStreamCombinations.length);
+ for (StreamCombinationTemplate combTemplate : chosenStreamCombinations) {
ArrayList<MandatoryStreamInformation> streamsInfo =
new ArrayList<MandatoryStreamInformation>();
streamsInfo.ensureCapacity(combTemplate.mStreamTemplates.length);
@@ -753,6 +761,9 @@ public final class MandatoryStreamCombination {
case s1440p:
formatSize = size1440p;
break;
+ case VGA:
+ formatSize = sizeVGAp;
+ break;
default:
formatSize = size720p;
}
diff --git a/core/java/android/inputmethodservice/InlineSuggestionSession.java b/core/java/android/inputmethodservice/InlineSuggestionSession.java
index 26197883c32f..509cbe09df69 100644
--- a/core/java/android/inputmethodservice/InlineSuggestionSession.java
+++ b/core/java/android/inputmethodservice/InlineSuggestionSession.java
@@ -38,6 +38,7 @@ import com.android.internal.view.IInlineSuggestionsResponseCallback;
import com.android.internal.view.InlineSuggestionsRequestInfo;
import java.lang.ref.WeakReference;
+import java.util.Collections;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -58,6 +59,9 @@ import java.util.function.Supplier;
class InlineSuggestionSession {
private static final String TAG = "ImsInlineSuggestionSession";
+ static final InlineSuggestionsResponse EMPTY_RESPONSE = new InlineSuggestionsResponse(
+ Collections.emptyList());
+
@NonNull
private final Handler mMainThreadHandler;
@NonNull
@@ -72,6 +76,10 @@ class InlineSuggestionSession {
private final Supplier<IBinder> mHostInputTokenSupplier;
@NonNull
private final Consumer<InlineSuggestionsResponse> mResponseConsumer;
+ // Indicate whether the previous call to the mResponseConsumer is empty or not. If it hasn't
+ // been called yet, the value would be null.
+ @Nullable
+ private Boolean mPreviousResponseIsEmpty;
/**
@@ -142,6 +150,7 @@ class InlineSuggestionSession {
@MainThread
void invalidate() {
if (mResponseCallback != null) {
+ consumeInlineSuggestionsResponse(EMPTY_RESPONSE);
mResponseCallback.invalidate();
mResponseCallback = null;
}
@@ -188,6 +197,17 @@ class InlineSuggestionSession {
if (DEBUG) {
Log.d(TAG, "IME receives response: " + response.getInlineSuggestions().size());
}
+ consumeInlineSuggestionsResponse(response);
+ }
+
+ @MainThread
+ void consumeInlineSuggestionsResponse(@NonNull InlineSuggestionsResponse response) {
+ boolean isResponseEmpty = response.getInlineSuggestions().isEmpty();
+ if (isResponseEmpty && Boolean.TRUE.equals(mPreviousResponseIsEmpty)) {
+ // No-op if both the previous response and current response are empty.
+ return;
+ }
+ mPreviousResponseIsEmpty = isResponseEmpty;
mResponseConsumer.accept(response);
}
diff --git a/core/java/android/inputmethodservice/InlineSuggestionSessionController.java b/core/java/android/inputmethodservice/InlineSuggestionSessionController.java
index c9f9059bed4f..8c0dd2a9bf59 100644
--- a/core/java/android/inputmethodservice/InlineSuggestionSessionController.java
+++ b/core/java/android/inputmethodservice/InlineSuggestionSessionController.java
@@ -213,6 +213,7 @@ class InlineSuggestionSessionController {
mImeInputViewStarted = false;
mImeInputStarted = false;
if (mSession != null && mSession.shouldSendImeStatus()) {
+ mSession.consumeInlineSuggestionsResponse(InlineSuggestionSession.EMPTY_RESPONSE);
try {
mSession.getRequestCallback().onInputMethodFinishInput();
} catch (RemoteException e) {
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index d8b1f41c86d5..5647bf90d2fb 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -471,6 +471,10 @@ public class InputMethodService extends AbstractInputMethodService {
final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = info -> {
onComputeInsets(mTmpInsets);
+ if (!mViewsCreated) {
+ // The IME views are not ready, keep visible insets untouched.
+ mTmpInsets.visibleTopInsets = 0;
+ }
if (isExtractViewShown()) {
// In true fullscreen mode, we just say the window isn't covering
// any content so we don't impact whatever is behind.
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index ef2a8a122e95..b36aeb89c02a 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -133,12 +133,23 @@ public class Build {
* <a href="/training/articles/security-key-attestation.html">key attestation</a> to obtain
* proof of the device's original identifiers.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). The profile
- * owner is an app that owns a managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link
+ * android.telephony.TelephonyManager#hasCarrierPrivileges}) on any active subscription.
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * android.app.role.RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -150,7 +161,7 @@ public class Build {
* the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
* higher, then a SecurityException is thrown.</li>
* </ul>
- * *
+ *
* @return The serial number if specified.
*/
@SuppressAutoDoc // No support for device / profile owner.
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 772845d4e683..8d65c92db52e 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -84,6 +84,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -189,6 +191,9 @@ public final class StrictMode {
// Only show an annoying dialog at most every 30 seconds
private static final long MIN_DIALOG_INTERVAL_MS = 30000;
+ // Only log a dropbox entry at most every 30 seconds
+ private static final long MIN_DROPBOX_INTERVAL_MS = 3000;
+
// How many Span tags (e.g. animations) to report.
private static final int MAX_SPAN_TAGS = 20;
@@ -1752,16 +1757,20 @@ public final class StrictMode {
// Not perfect, but fast and good enough for dup suppression.
Integer crashFingerprint = info.hashCode();
long lastViolationTime = 0;
- if (mLastViolationTime != null) {
- Long vtime = mLastViolationTime.get(crashFingerprint);
- if (vtime != null) {
- lastViolationTime = vtime;
+ long now = SystemClock.uptimeMillis();
+ if (sLogger == LOGCAT_LOGGER) { // Don't throttle it if there is a non-default logger
+ if (mLastViolationTime != null) {
+ Long vtime = mLastViolationTime.get(crashFingerprint);
+ if (vtime != null) {
+ lastViolationTime = vtime;
+ }
+ clampViolationTimeMap(mLastViolationTime, Math.max(MIN_LOG_INTERVAL_MS,
+ Math.max(MIN_DIALOG_INTERVAL_MS, MIN_DROPBOX_INTERVAL_MS)));
+ } else {
+ mLastViolationTime = new ArrayMap<>(1);
}
- } else {
- mLastViolationTime = new ArrayMap<>(1);
+ mLastViolationTime.put(crashFingerprint, now);
}
- long now = SystemClock.uptimeMillis();
- mLastViolationTime.put(crashFingerprint, now);
long timeSinceLastViolationMillis =
lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime);
@@ -1780,7 +1789,8 @@ public final class StrictMode {
penaltyMask |= PENALTY_DIALOG;
}
- if (info.penaltyEnabled(PENALTY_DROPBOX) && lastViolationTime == 0) {
+ if (info.penaltyEnabled(PENALTY_DROPBOX)
+ && timeSinceLastViolationMillis > MIN_DROPBOX_INTERVAL_MS) {
penaltyMask |= PENALTY_DROPBOX;
}
@@ -2215,6 +2225,23 @@ public final class StrictMode {
@UnsupportedAppUsage
private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<>();
+ /**
+ * Clamp the given map by removing elements with timestamp older than the given retainSince.
+ */
+ private static void clampViolationTimeMap(final @NonNull Map<Integer, Long> violationTime,
+ final long retainSince) {
+ final Iterator<Map.Entry<Integer, Long>> iterator = violationTime.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry<Integer, Long> e = iterator.next();
+ if (e.getValue() < retainSince) {
+ // Remove stale entries
+ iterator.remove();
+ }
+ }
+ // Ideally we'd cap the total size of the map, though it'll involve quickselect of topK,
+ // seems not worth it (saving some space immediately but they will be obsoleted soon anyway)
+ }
+
/** @hide */
public static void onVmPolicyViolation(Violation originStack) {
onVmPolicyViolation(originStack, false);
@@ -2238,13 +2265,17 @@ public final class StrictMode {
final long now = SystemClock.uptimeMillis();
long lastViolationTime;
long timeSinceLastViolationMillis = Long.MAX_VALUE;
- synchronized (sLastVmViolationTime) {
- if (sLastVmViolationTime.containsKey(fingerprint)) {
- lastViolationTime = sLastVmViolationTime.get(fingerprint);
- timeSinceLastViolationMillis = now - lastViolationTime;
- }
- if (timeSinceLastViolationMillis > MIN_VM_INTERVAL_MS) {
- sLastVmViolationTime.put(fingerprint, now);
+ if (sLogger == LOGCAT_LOGGER) { // Don't throttle it if there is a non-default logger
+ synchronized (sLastVmViolationTime) {
+ if (sLastVmViolationTime.containsKey(fingerprint)) {
+ lastViolationTime = sLastVmViolationTime.get(fingerprint);
+ timeSinceLastViolationMillis = now - lastViolationTime;
+ }
+ if (timeSinceLastViolationMillis > MIN_VM_INTERVAL_MS) {
+ sLastVmViolationTime.put(fingerprint, now);
+ }
+ clampViolationTimeMap(sLastVmViolationTime,
+ now - Math.max(MIN_VM_INTERVAL_MS, MIN_LOG_INTERVAL_MS));
}
}
if (timeSinceLastViolationMillis <= MIN_VM_INTERVAL_MS) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a415dc57e160..2465b0e41876 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2699,15 +2699,12 @@ public class UserManager {
* @param name the user's name
* @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_GUEST}.
* @param flags UserInfo flags that specify user properties.
- * @return the {@link UserInfo} object for the created user,
- * or throws {@link UserOperationException} if the user could not be created
- * and calling app is targeting {@link android.os.Build.VERSION_CODES#R} or above
- * (otherwise returns {@code null}).
+ * @return the {@link UserInfo} object for the created user, or {@code null} if the user
+ * could not be created.
*
- * @throws UserOperationException if the user could not be created and the calling app is
- * targeting {@link android.os.Build.VERSION_CODES#R} or above.
- * @hide
* @see UserInfo
+ *
+ * @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@@ -2716,8 +2713,7 @@ public class UserManager {
try {
return mService.createUserWithThrow(name, userType, flags);
} catch (ServiceSpecificException e) {
- return returnNullOrThrowUserOperationException(e,
- mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R);
+ return null;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2743,25 +2739,19 @@ public class UserManager {
* com.android.server.pm.UserManagerService#ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION}.
*
* @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_GUEST}.
- * @return the {@link UserInfo} object for the created user,
- * or throws {@link UserOperationException} if the user could not be created
- * and calling app is targeting {@link android.os.Build.VERSION_CODES#R} or above
- * (otherwise returns {@code null}).
- *
- * @throws UserOperationException if the user could not be created and the calling app is
- * targeting {@link android.os.Build.VERSION_CODES#R} or above.
+ * @return the {@link UserInfo} object for the created user.
*
+ * @throws UserOperationException if the user could not be created.
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
- public @Nullable UserInfo preCreateUser(@NonNull String userType)
+ public @NonNull UserInfo preCreateUser(@NonNull String userType)
throws UserOperationException {
try {
return mService.preCreateUserWithThrow(userType);
} catch (ServiceSpecificException e) {
- return returnNullOrThrowUserOperationException(e,
- mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R);
+ throw UserOperationException.from(e);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2771,18 +2761,14 @@ public class UserManager {
* Creates a guest user and configures it.
* @param context an application context
* @param name the name to set for the user
- * @return the {@link UserInfo} object for the created user,
- * or throws {@link UserOperationException} if the user could not be created
- * and calling app is targeting {@link android.os.Build.VERSION_CODES#R} or above
- * (otherwise returns {@code null}).
+ * @return the {@link UserInfo} object for the created user, or {@code null} if the user
+ * could not be created.
*
- * @throws UserOperationException if the user could not be created and the calling app is
- * targeting {@link android.os.Build.VERSION_CODES#R} or above.
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
- public UserInfo createGuest(Context context, String name) throws UserOperationException {
+ public UserInfo createGuest(Context context, String name) {
UserInfo guest = null;
try {
guest = mService.createUserWithThrow(name, USER_TYPE_FULL_GUEST, 0);
@@ -2791,8 +2777,7 @@ public class UserManager {
Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
}
} catch (ServiceSpecificException e) {
- return returnNullOrThrowUserOperationException(e,
- context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R);
+ return null;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2902,26 +2887,20 @@ public class UserManager {
* @param userId new user will be a profile of this user.
* @param disallowedPackages packages that will not be installed in the profile being created.
*
- * @return the {@link UserInfo} object for the created user,
- * or throws {@link UserOperationException} if the user could not be created
- * and calling app is targeting {@link android.os.Build.VERSION_CODES#R} or above
- * (otherwise returns {@code null}).
+ * @return the {@link UserInfo} object for the created user, or {@code null} if the user could
+ * not be created.
*
- * @throws UserOperationException if the user could not be created and the calling app is
- * targeting {@link android.os.Build.VERSION_CODES#R} or above.
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
public UserInfo createProfileForUser(String name, @NonNull String userType,
- @UserInfoFlag int flags, @UserIdInt int userId, String[] disallowedPackages)
- throws UserOperationException {
+ @UserInfoFlag int flags, @UserIdInt int userId, String[] disallowedPackages) {
try {
return mService.createProfileForUserWithThrow(name, userType, flags, userId,
disallowedPackages);
} catch (ServiceSpecificException e) {
- return returnNullOrThrowUserOperationException(e,
- mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R);
+ return null;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2938,13 +2917,12 @@ public class UserManager {
Manifest.permission.CREATE_USERS})
public UserInfo createProfileForUserEvenWhenDisallowed(String name,
@NonNull String userType, @UserInfoFlag int flags, @UserIdInt int userId,
- String[] disallowedPackages) throws UserOperationException {
+ String[] disallowedPackages) {
try {
return mService.createProfileForUserEvenWhenDisallowedWithThrow(name, userType, flags,
userId, disallowedPackages);
} catch (ServiceSpecificException e) {
- return returnNullOrThrowUserOperationException(e,
- mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R);
+ return null;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2955,18 +2933,14 @@ public class UserManager {
* restrictions and adds shared accounts.
*
* @param name profile's name
- * @return the {@link UserInfo} object for the created user,
- * or throws {@link UserOperationException} if the user could not be created
- * and calling app is targeting {@link android.os.Build.VERSION_CODES#R} or above
- * (otherwise returns {@code null}).
+ * @return the {@link UserInfo} object for the created user, or {@code null} if the user
+ * could not be created.
*
- * @throws UserOperationException if the user could not be created and the calling app is
- * targeting {@link android.os.Build.VERSION_CODES#R} or above.
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
- public UserInfo createRestrictedProfile(String name) throws UserOperationException {
+ public UserInfo createRestrictedProfile(String name) {
try {
UserHandle parentUserHandle = Process.myUserHandle();
UserInfo user = mService.createRestrictedProfileWithThrow(name,
@@ -2977,8 +2951,7 @@ public class UserManager {
}
return user;
} catch (ServiceSpecificException e) {
- return returnNullOrThrowUserOperationException(e,
- mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R);
+ return null;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -4009,15 +3982,15 @@ public class UserManager {
* Sets the user's photo.
* @param userId the user for whom to change the photo.
* @param icon the bitmap to set as the photo.
+ *
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- public void setUserIcon(@UserIdInt int userId, @NonNull Bitmap icon)
- throws UserOperationException {
+ public void setUserIcon(@UserIdInt int userId, @NonNull Bitmap icon) {
try {
mService.setUserIcon(userId, icon);
} catch (ServiceSpecificException e) {
- throw UserOperationException.from(e);
+ return;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -4027,6 +4000,10 @@ public class UserManager {
* Sets the context user's photo.
*
* @param icon the bitmap to set as the photo.
+ *
+ * @throws UserOperationException according to the function signature, but may not actually
+ * throw it in practice. Catch RuntimeException instead.
+ *
* @hide
*/
@SystemApi
diff --git a/core/java/android/os/strictmode/Violation.java b/core/java/android/os/strictmode/Violation.java
index 31c7d584fd65..0edb78a64243 100644
--- a/core/java/android/os/strictmode/Violation.java
+++ b/core/java/android/os/strictmode/Violation.java
@@ -18,7 +18,58 @@ package android.os.strictmode;
/** Root class for all StrictMode violations. */
public abstract class Violation extends Throwable {
+ private int mHashCode;
+ private boolean mHashCodeValid;
+
Violation(String message) {
super(message);
}
+
+ @Override
+ public int hashCode() {
+ synchronized (this) {
+ if (mHashCodeValid) {
+ return mHashCode;
+ }
+ final String message = getMessage();
+ final Throwable cause = getCause();
+ int hashCode = message != null ? message.hashCode() : getClass().hashCode();
+ hashCode = hashCode * 37 + calcStackTraceHashCode(getStackTrace());
+ hashCode = hashCode * 37 + (cause != null ? cause.toString().hashCode() : 0);
+ mHashCodeValid = true;
+ return mHashCode = hashCode;
+ }
+ }
+
+ @Override
+ public synchronized Throwable initCause(Throwable cause) {
+ mHashCodeValid = false;
+ return super.initCause(cause);
+ }
+
+ @Override
+ public void setStackTrace(StackTraceElement[] stackTrace) {
+ super.setStackTrace(stackTrace);
+ synchronized (this) {
+ mHashCodeValid = false;
+ }
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ mHashCodeValid = false;
+ return super.fillInStackTrace();
+ }
+
+ private static int calcStackTraceHashCode(final StackTraceElement[] stackTrace) {
+ int hashCode = 17;
+ if (stackTrace != null) {
+ for (int i = 0; i < stackTrace.length; i++) {
+ if (stackTrace[i] != null) {
+ hashCode = hashCode * 37 + stackTrace[i].hashCode();
+ }
+ }
+ }
+ return hashCode;
+ }
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 235b0830b9aa..e23102113e9f 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -71,7 +71,7 @@ interface IPermissionManager {
void grantRuntimePermission(String packageName, String permName, int userId);
- void revokeRuntimePermission(String packageName, String permName, int userId);
+ void revokeRuntimePermission(String packageName, String permName, int userId, String reason);
void resetRuntimePermissions();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4abb2c59e1c8..64d9c9dcc6e0 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12009,7 +12009,7 @@ public final class Settings {
* @see #ENABLE_RESTRICTED_BUCKET
* @hide
*/
- public static final int DEFAULT_ENABLE_RESTRICTED_BUCKET = 1;
+ public static final int DEFAULT_ENABLE_RESTRICTED_BUCKET = 0;
/**
* Whether or not app auto restriction is enabled. When it is enabled, settings app will
diff --git a/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl b/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
index bf0bb9e2a41f..7cd372fe97d8 100644
--- a/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
+++ b/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
@@ -29,6 +29,12 @@ import android.service.autofill.InlinePresentation;
oneway interface IInlineSuggestionRenderService {
void renderSuggestion(in IInlineSuggestionUiCallback callback,
in InlinePresentation presentation, int width, int height,
- in IBinder hostInputToken, int displayId);
+ in IBinder hostInputToken, int displayId, int userId, int sessionId);
void getInlineSuggestionsRendererInfo(in RemoteCallback callback);
+
+ /**
+ * Releases the inline suggestion SurfaceControlViewHosts hosted in the service, for the
+ * provided userId and sessionId.
+ */
+ void destroySuggestionViews(int userId, int sessionId);
}
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 8790fb2299f5..839caff5c3d4 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -41,6 +41,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.lang.ref.WeakReference;
/**
@@ -82,7 +84,7 @@ public abstract class InlineSuggestionRenderService extends Service {
Boolean newValue) {
if (evicted) {
Log.w(TAG,
- "Hit max=100 entries in the cache. Releasing oldest one to make "
+ "Hit max=30 entries in the cache. Releasing oldest one to make "
+ "space.");
key.releaseSurfaceControlViewHost();
}
@@ -130,7 +132,7 @@ public abstract class InlineSuggestionRenderService extends Service {
private void handleRenderSuggestion(IInlineSuggestionUiCallback callback,
InlinePresentation presentation, int width, int height, IBinder hostInputToken,
- int displayId) {
+ int displayId, int userId, int sessionId) {
if (hostInputToken == null) {
try {
callback.onError();
@@ -192,7 +194,8 @@ public abstract class InlineSuggestionRenderService extends Service {
}
return true;
});
- final InlineSuggestionUiImpl uiImpl = new InlineSuggestionUiImpl(host, mMainHandler);
+ final InlineSuggestionUiImpl uiImpl = new InlineSuggestionUiImpl(host, mMainHandler,
+ userId, sessionId);
mActiveInlineSuggestions.put(uiImpl, true);
// We post the callback invocation to the end of the main thread handler queue, to make
@@ -218,6 +221,18 @@ public abstract class InlineSuggestionRenderService extends Service {
callback.sendResult(rendererInfo);
}
+ private void handleDestroySuggestionViews(int userId, int sessionId) {
+ Log.v(TAG, "handleDestroySuggestionViews called for " + userId + ":" + sessionId);
+ for (final InlineSuggestionUiImpl inlineSuggestionUi :
+ mActiveInlineSuggestions.snapshot().keySet()) {
+ if (inlineSuggestionUi.mUserId == userId
+ && inlineSuggestionUi.mSessionId == sessionId) {
+ Log.v(TAG, "Destroy " + inlineSuggestionUi);
+ inlineSuggestionUi.releaseSurfaceControlViewHost();
+ }
+ }
+ }
+
/**
* A wrapper class around the {@link InlineSuggestionUiImpl} to ensure it's not strongly
* reference by the remote system server process.
@@ -260,10 +275,15 @@ public abstract class InlineSuggestionRenderService extends Service {
private SurfaceControlViewHost mViewHost;
@NonNull
private final Handler mHandler;
+ private final int mUserId;
+ private final int mSessionId;
- InlineSuggestionUiImpl(SurfaceControlViewHost viewHost, Handler handler) {
+ InlineSuggestionUiImpl(SurfaceControlViewHost viewHost, Handler handler, int userId,
+ int sessionId) {
this.mViewHost = viewHost;
this.mHandler = handler;
+ this.mUserId = userId;
+ this.mSessionId = sessionId;
}
/**
@@ -302,6 +322,16 @@ public abstract class InlineSuggestionRenderService extends Service {
}
}
+ /** @hide */
+ @Override
+ protected final void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
+ @NonNull String[] args) {
+ pw.println("mActiveInlineSuggestions: " + mActiveInlineSuggestions.size());
+ for (InlineSuggestionUiImpl impl : mActiveInlineSuggestions.snapshot().keySet()) {
+ pw.printf("ui: [%s] - [%d] [%d]\n", impl, impl.mUserId, impl.mSessionId);
+ }
+ }
+
@Override
@Nullable
public final IBinder onBind(@NonNull Intent intent) {
@@ -311,11 +341,12 @@ public abstract class InlineSuggestionRenderService extends Service {
@Override
public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
@NonNull InlinePresentation presentation, int width, int height,
- @Nullable IBinder hostInputToken, int displayId) {
+ @Nullable IBinder hostInputToken, int displayId, int userId,
+ int sessionId) {
mMainHandler.sendMessage(
obtainMessage(InlineSuggestionRenderService::handleRenderSuggestion,
InlineSuggestionRenderService.this, callback, presentation,
- width, height, hostInputToken, displayId));
+ width, height, hostInputToken, displayId, userId, sessionId));
}
@Override
@@ -324,6 +355,12 @@ public abstract class InlineSuggestionRenderService extends Service {
InlineSuggestionRenderService::handleGetInlineSuggestionsRendererInfo,
InlineSuggestionRenderService.this, callback));
}
+ @Override
+ public void destroySuggestionViews(int userId, int sessionId) {
+ mMainHandler.sendMessage(obtainMessage(
+ InlineSuggestionRenderService::handleDestroySuggestionViews,
+ InlineSuggestionRenderService.this, userId, sessionId));
+ }
}.asBinder();
}
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index 4e5aa0018b61..6bd376a19fc5 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -296,6 +296,10 @@ public abstract class ControlsProviderService extends Service {
/**
* Request SystemUI to prompt the user to add a control to favorites.
+ * <br>
+ * SystemUI may not honor this request in some cases, for example if the requested
+ * {@link Control} is already a favorite, or the requesting package is not currently in the
+ * foreground.
*
* @param context A context
* @param componentName Component name of the {@link ControlsProviderService}
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 8b5af29517cb..ef9d990168d2 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -21,6 +21,7 @@ import static android.view.InsetsState.ITYPE_IME;
import android.annotation.Nullable;
import android.inputmethodservice.InputMethodService;
+import android.os.IBinder;
import android.os.Parcel;
import android.text.TextUtils;
import android.view.SurfaceControl.Transaction;
@@ -153,6 +154,15 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
return mIsRequestedVisibleAwaitingControl || isRequestedVisible();
}
+ @Override
+ public void onPerceptible(boolean perceptible) {
+ super.onPerceptible(perceptible);
+ final IBinder window = mController.getHost().getWindowToken();
+ if (window != null) {
+ getImm().reportPerceptible(window, perceptible);
+ }
+ }
+
private boolean isDummyOrEmptyEditor(EditorInfo info) {
// TODO(b/123044812): Handle dummy input gracefully in IME Insets API
return info == null || (info.fieldId <= 0 && info.inputType <= 0);
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java
index 74c186948b2f..3431c3ecc310 100644
--- a/core/java/android/view/InsetsAnimationControlCallbacks.java
+++ b/core/java/android/view/InsetsAnimationControlCallbacks.java
@@ -16,6 +16,7 @@
package android.view;
+import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation.Bounds;
/**
@@ -64,4 +65,15 @@ public interface InsetsAnimationControlCallbacks {
* previous calls to applySurfaceParams.
*/
void releaseSurfaceControlFromRt(SurfaceControl sc);
+
+ /**
+ * Reports that the perceptibility of the given types has changed to the given value.
+ *
+ * A type is perceptible if it is not (almost) entirely off-screen and not (almost) entirely
+ * transparent.
+ *
+ * @param types the (public) types whose perceptibility has changed
+ * @param perceptible true, if the types are now perceptible, false if they are not perceptible
+ */
+ void reportPerceptible(@InsetsType int types, boolean perceptible);
}
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index baeae2fd2cdd..31da83ad5137 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -87,6 +87,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private float mPendingAlpha = 1.0f;
@VisibleForTesting(visibility = PACKAGE)
public boolean mReadyDispatched;
+ private Boolean mPerceptible;
@VisibleForTesting
public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, Rect frame,
@@ -121,6 +122,14 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
new Bounds(mHiddenInsets, mShownInsets));
}
+ private boolean calculatePerceptible(Insets currentInsets, float currentAlpha) {
+ return 100 * currentInsets.left >= 5 * (mShownInsets.left - mHiddenInsets.left)
+ && 100 * currentInsets.top >= 5 * (mShownInsets.top - mHiddenInsets.top)
+ && 100 * currentInsets.right >= 5 * (mShownInsets.right - mHiddenInsets.right)
+ && 100 * currentInsets.bottom >= 5 * (mShownInsets.bottom - mHiddenInsets.bottom)
+ && currentAlpha >= 0.5f;
+ }
+
@Override
public boolean hasZeroInsetsIme() {
return mHasZeroInsetsIme;
@@ -175,6 +184,11 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
mPendingInsets = sanitize(insets);
mPendingAlpha = sanitize(alpha);
mController.scheduleApplyChangeInsets(this);
+ boolean perceptible = calculatePerceptible(mPendingInsets, mPendingAlpha);
+ if (mPerceptible == null || perceptible != mPerceptible) {
+ mController.reportPerceptible(mTypes, perceptible);
+ mPerceptible = perceptible;
+ }
}
@VisibleForTesting
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 0e71b7643b7d..123604489da4 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -90,6 +90,11 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
// Since we don't push the SurfaceParams to the RT we can release directly
sc.release();
}
+
+ @Override
+ public void reportPerceptible(int types, boolean perceptible) {
+ mMainThreadHandler.post(() -> mOuterCallbacks.reportPerceptible(types, perceptible));
+ }
};
@UiThread
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 5f99bfe432a4..c6be91fa1bf5 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -35,6 +35,7 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.os.CancellationSignal;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Trace;
import android.util.ArraySet;
import android.util.Log;
@@ -165,6 +166,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
/** @see ViewRootImpl#dipToPx */
int dipToPx(int dips);
+
+ /**
+ * @return token associated with the host, if it has one.
+ */
+ @Nullable
+ IBinder getWindowToken();
}
private static final String TAG = "InsetsController";
@@ -507,6 +514,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
/** Set of inset types for which an animation was started since last resetting this field */
private @InsetsType int mLastStartedAnimTypes;
+ /** Set of inset types which cannot be controlled by the user animation */
+ private @InsetsType int mDisabledUserAnimationInsetsTypes;
+
+ private Runnable mInvokeControllableInsetsChangedListeners =
+ this::invokeControllableInsetsChangedListeners;
+
public InsetsController(Host host) {
this(host, (controller, type) -> {
if (type == ITYPE_IME) {
@@ -621,22 +634,57 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private void updateState(InsetsState newState) {
mState.setDisplayFrame(newState.getDisplayFrame());
- for (int i = 0; i < InsetsState.SIZE; i++) {
- InsetsSource source = newState.peekSource(i);
- if (source == null) continue;;
- getSourceConsumer(source.getType()).updateSource(source);
+ @InsetsType int disabledUserAnimationTypes = 0;
+ @InsetsType int[] cancelledUserAnimationTypes = {0};
+ for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
+ InsetsSource source = newState.peekSource(type);
+ if (source == null) continue;
+ @AnimationType int animationType = getAnimationType(type);
+ if (!source.isUserControllable()) {
+ @InsetsType int insetsType = toPublicType(type);
+ // The user animation is not allowed when visible frame is empty.
+ disabledUserAnimationTypes |= insetsType;
+ if (animationType == ANIMATION_TYPE_USER) {
+ // Existing user animation needs to be cancelled.
+ animationType = ANIMATION_TYPE_NONE;
+ cancelledUserAnimationTypes[0] |= insetsType;
+ }
+ }
+ getSourceConsumer(type).updateSource(source, animationType);
}
- for (int i = 0; i < InsetsState.SIZE; i++) {
- InsetsSource source = mState.peekSource(i);
+ for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
+ InsetsSource source = mState.peekSource(type);
if (source == null) continue;
- if (newState.peekSource(source.getType()) == null) {
- mState.removeSource(source.getType());
+ if (newState.peekSource(type) == null) {
+ mState.removeSource(type);
}
}
if (mCaptionInsetsHeight != 0) {
mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
mFrame.right, mFrame.top + mCaptionInsetsHeight));
}
+
+ updateDisabledUserAnimationTypes(disabledUserAnimationTypes);
+
+ if (cancelledUserAnimationTypes[0] != 0) {
+ mHandler.post(() -> show(cancelledUserAnimationTypes[0]));
+ }
+ }
+
+ private void updateDisabledUserAnimationTypes(@InsetsType int disabledUserAnimationTypes) {
+ @InsetsType int diff = mDisabledUserAnimationInsetsTypes ^ disabledUserAnimationTypes;
+ if (diff != 0) {
+ for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
+ InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+ if (consumer.getControl() != null
+ && (toPublicType(consumer.getType()) & diff) != 0) {
+ mHandler.removeCallbacks(mInvokeControllableInsetsChangedListeners);
+ mHandler.post(mInvokeControllableInsetsChangedListeners);
+ break;
+ }
+ }
+ mDisabledUserAnimationInsetsTypes = disabledUserAnimationTypes;
+ }
}
private boolean captionInsetsUnchanged() {
@@ -840,6 +888,18 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
+ " while an existing " + Type.toString(mTypesBeingCancelled)
+ " is being cancelled.");
}
+ if (animationType == ANIMATION_TYPE_USER) {
+ final @InsetsType int disabledTypes = types & mDisabledUserAnimationInsetsTypes;
+ if (DEBUG) Log.d(TAG, "user animation disabled types: " + disabledTypes);
+ types &= ~mDisabledUserAnimationInsetsTypes;
+
+ if (fromIme && (disabledTypes & ime()) != 0
+ && !mState.getSource(ITYPE_IME).isVisible()) {
+ // We've requested IMM to show IME, but the IME is not controllable. We need to
+ // cancel the request.
+ getSourceConsumer(ITYPE_IME).hide(true, animationType);
+ }
+ }
if (types == 0) {
// nothing to animate.
listener.onCancelled(null);
@@ -1313,7 +1373,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@InsetsType int result = 0;
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
- if (consumer.getControl() != null) {
+ InsetsSource source = mState.peekSource(consumer.mType);
+ if (consumer.getControl() != null && source != null && source.isUserControllable()) {
result |= toPublicType(consumer.mType);
}
}
@@ -1324,6 +1385,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
* @return The types that are now animating due to a listener invoking control/show/hide
*/
private @InsetsType int invokeControllableInsetsChangedListeners() {
+ mHandler.removeCallbacks(mInvokeControllableInsetsChangedListeners);
mLastStartedAnimTypes = 0;
@InsetsType int types = calculateControllableTypes();
int size = mControllableInsetsChangedListeners.size();
@@ -1353,6 +1415,18 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mHost.releaseSurfaceControlFromRt(sc);
}
+ @Override
+ public void reportPerceptible(int types, boolean perceptible) {
+ final ArraySet<Integer> internalTypes = toInternalType(types);
+ final int size = mSourceConsumers.size();
+ for (int i = 0; i < size; i++) {
+ final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+ if (internalTypes.contains(consumer.getType())) {
+ consumer.onPerceptible(perceptible);
+ }
+ }
+ }
+
Host getHost() {
return mHost;
}
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 15b9a9330392..dbf75705c073 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -92,6 +92,11 @@ public class InsetsSource implements Parcelable {
return mVisible;
}
+ boolean isUserControllable() {
+ // If mVisibleFrame is null, it will be the same area as mFrame.
+ return mVisibleFrame == null || !mVisibleFrame.isEmpty();
+ }
+
/**
* Calculates the insets this source will cause to a client window.
*
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 565846638acc..40e6f4b2fce8 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -18,8 +18,8 @@ package android.view;
import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.AnimationType;
-import static android.view.InsetsState.getDefaultVisibility;
import static android.view.InsetsController.DEBUG;
+import static android.view.InsetsState.getDefaultVisibility;
import static android.view.InsetsState.toPublicType;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
@@ -261,6 +261,15 @@ public class InsetsSourceConsumer {
}
/**
+ * Reports that this source's perceptibility has changed
+ *
+ * @param perceptible true if the source is perceptible, false otherwise.
+ * @see InsetsAnimationControlCallbacks#reportPerceptible
+ */
+ public void onPerceptible(boolean perceptible) {
+ }
+
+ /**
* Notify listeners that window is now hidden.
*/
void notifyHidden() {
@@ -275,9 +284,9 @@ public class InsetsSourceConsumer {
}
@VisibleForTesting(visibility = PACKAGE)
- public void updateSource(InsetsSource newSource) {
+ public void updateSource(InsetsSource newSource, @AnimationType int animationType) {
InsetsSource source = mState.peekSource(mType);
- if (source == null || mController.getAnimationType(mType) == ANIMATION_TYPE_NONE
+ if (source == null || animationType == ANIMATION_TYPE_NONE
|| source.getFrame().equals(newSource.getFrame())) {
mPendingFrame = null;
mPendingVisibleFrame = null;
@@ -286,7 +295,7 @@ public class InsetsSourceConsumer {
}
// Frame is changing while animating. Keep note of the new frame but keep existing frame
- // until animaition is finished.
+ // until animation is finished.
newSource = new InsetsSource(newSource);
mPendingFrame = new Rect(newSource.getFrame());
mPendingVisibleFrame = newSource.getVisibleFrame() != null
@@ -339,5 +348,6 @@ public class InsetsSourceConsumer {
t.hide(mSourceControl.getLeash());
}
t.apply();
+ onPerceptible(mRequestedVisible);
}
}
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 19eff72ca814..51b0c6b59f3c 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -487,6 +487,21 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int FLAG_TAINTED = 0x80000000;
/**
+ * Private flag indicating that this event was synthesized by the system and should be delivered
+ * to the accessibility focused view first. When being dispatched such an event is not handled
+ * by predecessors of the accessibility focused view and after the event reaches that view the
+ * flag is cleared and normal event dispatch is performed. This ensures that the platform can
+ * click on any view that has accessibility focus which is semantically equivalent to asking the
+ * view to perform a click accessibility action but more generic as views not implementing click
+ * action correctly can still be activated.
+ *
+ * @hide
+ * @see #isTargetAccessibilityFocus()
+ * @see #setTargetAccessibilityFocus(boolean)
+ */
+ public static final int FLAG_TARGET_ACCESSIBILITY_FOCUS = 0x40000000;
+
+ /**
* Flag indicating the motion event intersected the top edge of the screen.
*/
public static final int EDGE_TOP = 0x00000001;
@@ -2140,6 +2155,20 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
/** @hide */
+ public boolean isTargetAccessibilityFocus() {
+ final int flags = getFlags();
+ return (flags & FLAG_TARGET_ACCESSIBILITY_FOCUS) != 0;
+ }
+
+ /** @hide */
+ public void setTargetAccessibilityFocus(boolean targetsFocus) {
+ final int flags = getFlags();
+ nativeSetFlags(mNativePtr, targetsFocus
+ ? flags | FLAG_TARGET_ACCESSIBILITY_FOCUS
+ : flags & ~FLAG_TARGET_ACCESSIBILITY_FOCUS);
+ }
+
+ /** @hide */
public final boolean isHoverExitPending() {
final int flags = getFlags();
return (flags & FLAG_HOVER_EXIT_PENDING) != 0;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3b3836582b16..daeb1c9c1e01 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -63,8 +63,10 @@ import dalvik.system.CloseGuard;
import libcore.util.NativeAllocationRegistry;
import java.io.Closeable;
+import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.util.ArrayList;
import java.util.Objects;
/**
@@ -226,24 +228,86 @@ public final class SurfaceControl implements Parcelable {
private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
int transformHint);
+ @Nullable
+ @GuardedBy("mLock")
+ private ArrayList<OnReparentListener> mReparentListeners;
+
+ /**
+ * Listener to observe surface reparenting.
+ *
+ * @hide
+ */
+ public interface OnReparentListener {
+
+ /**
+ * Callback for reparenting surfaces.
+ *
+ * Important: You should only interact with the provided surface control
+ * only if you have a contract with its owner to avoid them closing it
+ * under you or vise versa.
+ *
+ * @param transaction The transaction that would commit reparenting.
+ * @param parent The future parent surface.
+ */
+ void onReparent(@NonNull Transaction transaction, @Nullable SurfaceControl parent);
+ }
+
private final CloseGuard mCloseGuard = CloseGuard.get();
private String mName;
- /**
+
+ /**
* @hide
*/
public long mNativeObject;
private long mNativeHandle;
- // TODO: Move this to native.
- private final Object mSizeLock = new Object();
- @GuardedBy("mSizeLock")
+ // TODO: Move width/height to native and fix locking through out.
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
private int mWidth;
- @GuardedBy("mSizeLock")
+ @GuardedBy("mLock")
private int mHeight;
+ private WeakReference<View> mLocalOwnerView;
+
static Transaction sGlobalTransaction;
static long sTransactionNestCount = 0;
+ /**
+ * Adds a reparenting listener.
+ *
+ * @param listener The listener.
+ * @return Whether listener was added.
+ *
+ * @hide
+ */
+ public boolean addOnReparentListener(@NonNull OnReparentListener listener) {
+ synchronized (mLock) {
+ if (mReparentListeners == null) {
+ mReparentListeners = new ArrayList<>(1);
+ }
+ return mReparentListeners.add(listener);
+ }
+ }
+
+ /**
+ * Removes a reparenting listener.
+ *
+ * @param listener The listener.
+ * @return Whether listener was removed.
+ *
+ * @hide
+ */
+ public boolean removeOnReparentListener(@NonNull OnReparentListener listener) {
+ synchronized (mLock) {
+ final boolean removed = mReparentListeners.remove(listener);
+ if (mReparentListeners.isEmpty()) {
+ mReparentListeners = null;
+ }
+ return removed;
+ }
+ }
+
/* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
/**
@@ -455,6 +519,7 @@ public final class SurfaceControl implements Parcelable {
mName = other.mName;
mWidth = other.mWidth;
mHeight = other.mHeight;
+ mLocalOwnerView = other.mLocalOwnerView;
assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject));
}
@@ -553,6 +618,7 @@ public final class SurfaceControl implements Parcelable {
private int mHeight;
private int mFormat = PixelFormat.OPAQUE;
private String mName;
+ private WeakReference<View> mLocalOwnerView;
private SurfaceControl mParent;
private SparseIntArray mMetadata;
@@ -587,7 +653,8 @@ public final class SurfaceControl implements Parcelable {
"Only buffer layers can set a valid buffer size.");
}
return new SurfaceControl(
- mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata);
+ mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
+ mLocalOwnerView);
}
/**
@@ -602,6 +669,27 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Set the local owner view for the surface. This view is only
+ * valid in the same process and is not transferred in an IPC.
+ *
+ * Note: This is used for cases where we want to know the view
+ * that manages the surface control while intercepting reparenting.
+ * A specific example is InlineContentView which exposes is surface
+ * control for reparenting as a way to implement clipping of several
+ * InlineContentView instances within a certain area.
+ *
+ * @param view The owner view.
+ * @return This builder.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setLocalOwnerView(@NonNull View view) {
+ mLocalOwnerView = new WeakReference<>(view);
+ return this;
+ }
+
+ /**
* Set the initial size of the controlled surface's buffers in pixels.
*
* @param width The buffer width in pixels.
@@ -858,7 +946,7 @@ public final class SurfaceControl implements Parcelable {
* @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
*/
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
- SurfaceControl parent, SparseIntArray metadata)
+ SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView)
throws OutOfResourcesException, IllegalArgumentException {
if (name == null) {
throw new IllegalArgumentException("name must not be null");
@@ -867,6 +955,7 @@ public final class SurfaceControl implements Parcelable {
mName = name;
mWidth = w;
mHeight = h;
+ mLocalOwnerView = localOwnerView;
Parcel metaParcel = Parcel.obtain();
try {
if (metadata != null && metadata.size() > 0) {
@@ -1307,7 +1396,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public int getWidth() {
- synchronized (mSizeLock) {
+ synchronized (mLock) {
return mWidth;
}
}
@@ -1316,11 +1405,22 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public int getHeight() {
- synchronized (mSizeLock) {
+ synchronized (mLock) {
return mHeight;
}
}
+ /**
+ * Gets the local view that owns this surface.
+ *
+ * @return The owner view.
+ *
+ * @hide
+ */
+ public @Nullable View getLocalOwnerView() {
+ return (mLocalOwnerView != null) ? mLocalOwnerView.get() : null;
+ }
+
@Override
public String toString() {
return "Surface(name=" + mName + ")/@0x" +
@@ -2165,6 +2265,9 @@ public final class SurfaceControl implements Parcelable {
public long mNativeObject;
private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
+ private final ArrayMap<SurfaceControl, SurfaceControl> mReparentedSurfaces =
+ new ArrayMap<>();
+
Runnable mFreeNativeResources;
private static final float[] INVALID_COLOR = {-1, -1, -1};
@@ -2205,6 +2308,8 @@ public final class SurfaceControl implements Parcelable {
*/
@Override
public void close() {
+ mResizedSurfaces.clear();
+ mReparentedSurfaces.clear();
mFreeNativeResources.run();
mNativeObject = 0;
}
@@ -2215,6 +2320,7 @@ public final class SurfaceControl implements Parcelable {
*/
public void apply(boolean sync) {
applyResizedSurfaces();
+ notifyReparentedSurfaces();
nativeApplyTransaction(mNativeObject, sync);
}
@@ -2222,7 +2328,7 @@ public final class SurfaceControl implements Parcelable {
for (int i = mResizedSurfaces.size() - 1; i >= 0; i--) {
final Point size = mResizedSurfaces.valueAt(i);
final SurfaceControl surfaceControl = mResizedSurfaces.keyAt(i);
- synchronized (surfaceControl.mSizeLock) {
+ synchronized (surfaceControl.mLock) {
surfaceControl.mWidth = size.x;
surfaceControl.mHeight = size.y;
}
@@ -2230,6 +2336,22 @@ public final class SurfaceControl implements Parcelable {
mResizedSurfaces.clear();
}
+ private void notifyReparentedSurfaces() {
+ final int reparentCount = mReparentedSurfaces.size();
+ for (int i = reparentCount - 1; i >= 0; i--) {
+ final SurfaceControl child = mReparentedSurfaces.keyAt(i);
+ synchronized (child.mLock) {
+ final int listenerCount = (child.mReparentListeners != null)
+ ? child.mReparentListeners.size() : 0;
+ for (int j = 0; j < listenerCount; j++) {
+ final OnReparentListener listener = child.mReparentListeners.get(j);
+ listener.onReparent(this, mReparentedSurfaces.valueAt(i));
+ }
+ mReparentedSurfaces.removeAt(i);
+ }
+ }
+ }
+
/**
* Toggle the visibility of a given Layer and it's sub-tree.
*
@@ -2632,6 +2754,7 @@ public final class SurfaceControl implements Parcelable {
otherObject = newParent.mNativeObject;
}
nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
+ mReparentedSurfaces.put(sc, newParent);
return this;
}
@@ -2912,6 +3035,8 @@ public final class SurfaceControl implements Parcelable {
}
mResizedSurfaces.putAll(other.mResizedSurfaces);
other.mResizedSurfaces.clear();
+ mReparentedSurfaces.putAll(other.mReparentedSurfaces);
+ other.mReparentedSurfaces.clear();
nativeMergeTransaction(mNativeObject, other.mNativeObject);
return this;
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 90e1eab09fd6..0d21eb5cf920 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -44,7 +44,6 @@ import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceControlViewHost;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityEmbeddedConnection;
@@ -988,6 +987,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
.setName(name)
+ .setLocalOwnerView(this)
.setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
.setBufferSize(mSurfaceWidth, mSurfaceHeight)
.setFormat(mFormat)
@@ -996,6 +996,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
.build();
mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
.setName("Background for -" + name)
+ .setLocalOwnerView(this)
.setOpaque(true)
.setColorLayer()
.setParent(mSurfaceControl)
@@ -1051,11 +1052,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// we still need to latch a buffer).
// b/28866173
if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
- mTmpTransaction.setPosition(mSurfaceControl, mScreenRect.left,
- mScreenRect.top);
- mTmpTransaction.setMatrix(mSurfaceControl,
- mScreenRect.width() / (float) mSurfaceWidth, 0.0f, 0.0f,
- mScreenRect.height() / (float) mSurfaceHeight);
+ onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
+ mScreenRect.left, /*positionLeft*/
+ mScreenRect.top /*positionTop*/ ,
+ mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
+ mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
+
// Set a window crop when creating the surface or changing its size to
// crop the buffer to the surface size since the buffer producer may
// use SCALING_MODE_SCALE and submit a larger size than the surface
@@ -1211,6 +1213,40 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
Surface viewRootSurface, long nextViewRootFrameNumber) {
}
+ /**
+ * Sets the surface position and scale. Can be called on
+ * the UI thread as well as on the renderer thread.
+ *
+ * @param transaction Transaction in which to execute.
+ * @param surface Surface whose location to set.
+ * @param positionLeft The left position to set.
+ * @param positionTop The top position to set.
+ * @param postScaleX The X axis post scale
+ * @param postScaleY The Y axis post scale
+ *
+ * @hide
+ */
+ protected void onSetSurfacePositionAndScaleRT(@NonNull Transaction transaction,
+ @NonNull SurfaceControl surface, int positionLeft, int positionTop,
+ float postScaleX, float postScaleY) {
+ transaction.setPosition(surface, positionLeft, positionTop);
+ transaction.setMatrix(surface, postScaleX /*dsdx*/, 0f /*dtdx*/,
+ 0f /*dtdy*/, postScaleY /*dsdy*/);
+ }
+
+ /** @hide */
+ public void requestUpdateSurfacePositionAndScale() {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
+ mScreenRect.left, /*positionLeft*/
+ mScreenRect.top/*positionTop*/ ,
+ mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
+ mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
+ mTmpTransaction.apply();
+ }
+
private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
Rect position, long frameNumber) {
final ViewRootImpl viewRoot = getViewRootImpl();
@@ -1219,16 +1255,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
frameNumber);
}
- t.setPosition(surface, position.left, position.top);
- t.setMatrix(surface,
- position.width() / (float) mSurfaceWidth,
- 0.0f, 0.0f,
- position.height() / (float) mSurfaceHeight);
+ onSetSurfacePositionAndScaleRT(t, surface,
+ position.left /*positionLeft*/,
+ position.top /*positionTop*/,
+ position.width() / (float) mSurfaceWidth /*postScaleX*/,
+ position.height() / (float) mSurfaceHeight /*postScaleY*/);
+
if (mViewVisibility) {
t.show(surface);
}
}
+ /**
+ * @return The last render position of the backing surface or an empty rect.
+ *
+ * @hide
+ */
+ public @NonNull Rect getSurfaceRenderPosition() {
+ return mRTLastReportedPosition;
+ }
+
private void setParentSpaceRectangle(Rect position, long frameNumber) {
final ViewRootImpl viewRoot = getViewRootImpl();
final boolean useBLAST = viewRoot.isDrawingToBLASTTransaction();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1226202dfdf9..df1c672eb9eb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14274,6 +14274,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
+ if (event.isTargetAccessibilityFocus()) {
+ // We don't have focus or no virtual descendant has it, do not handle the event.
+ if (!isAccessibilityFocusedViewOrHost()) {
+ return false;
+ }
+ // We have focus and got the event, then use normal event dispatch.
+ event.setTargetAccessibilityFocus(false);
+ }
boolean result = false;
if (mInputEventConsistencyVerifier != null) {
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 0d2d4d13eb38..ffeeb806ba54 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -500,12 +500,13 @@ public class ViewConfiguration {
*/
public static ViewConfiguration get(Context context) {
if (!context.isUiContext() && vmIncorrectContextUseEnabled()) {
- final String errorMessage = "Tried to access UI constants from a non-visual Context.";
+ final String errorMessage = "Tried to access UI constants from a non-visual Context:"
+ + context;
final String message = "UI constants, such as display metrics or window metrics, "
+ "must be accessed from Activity or other visual Context. "
+ "Use an Activity or a Context created with "
+ "Context#createWindowContext(int, Bundle), which are adjusted to the "
- + "configuration and visual bounds of an area on screen.";
+ + "configuration and visual bounds of an area on screen";
final Exception exception = new IllegalArgumentException(errorMessage);
StrictMode.onIncorrectContextUsed(message, exception);
Log.e(TAG, errorMessage + message, exception);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e3362aafbcd4..77fedd7c30d4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2048,8 +2048,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = childrenCount - 1; i >= 0; i--) {
final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
+ View childWithAccessibilityFocus =
+ event.isTargetAccessibilityFocus()
+ ? findChildWithAccessibilityFocus()
+ : null;
+
if (!child.canReceivePointerEvents()
|| !isTransformedTouchPointInView(x, y, child, null)) {
+
+ // If there is a view that has accessibility focus we want it
+ // to get the event first and if not handled we will perform a
+ // normal dispatch. We may do a double iteration but this is
+ // safer given the timeframe.
+ if (childWithAccessibilityFocus != null) {
+ if (childWithAccessibilityFocus != child) {
+ continue;
+ }
+ childWithAccessibilityFocus = null;
+ i = childrenCount - 1;
+ }
+ event.setTargetAccessibilityFocus(false);
continue;
}
final PointerIcon pointerIcon =
@@ -2617,6 +2635,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
}
+ // If the event targets the accessibility focused view and this is it, start
+ // normal event dispatch. Maybe a descendant is what will handle the click.
+ if (ev.isTargetAccessibilityFocus() && isAccessibilityFocusedViewOrHost()) {
+ ev.setTargetAccessibilityFocus(false);
+ }
+
boolean handled = false;
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
@@ -2647,6 +2671,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// so this view group continues to intercept touches.
intercepted = true;
}
+
+ // If intercepted, start normal event dispatch. Also if there is already
+ // a view that is handling the gesture, do normal event dispatch.
+ if (intercepted || mFirstTouchTarget != null) {
+ ev.setTargetAccessibilityFocus(false);
+ }
+
// Check for cancelation.
final boolean canceled = resetCancelNextUpFlag(this)
|| actionMasked == MotionEvent.ACTION_CANCEL;
@@ -2658,6 +2689,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
TouchTarget newTouchTarget = null;
boolean alreadyDispatchedToNewTouchTarget = false;
if (!canceled && !intercepted) {
+ // If the event is targeting accessibility focus we give it to the
+ // view that has accessibility focus and if it does not handle it
+ // we clear the flag and dispatch the event to all children as usual.
+ // We are looking up the accessibility focused host to avoid keeping
+ // state since these events are very rare.
+ View childWithAccessibilityFocus = ev.isTargetAccessibilityFocus()
+ ? findChildWithAccessibilityFocus() : null;
+
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
@@ -2720,6 +2759,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
alreadyDispatchedToNewTouchTarget = true;
break;
}
+
+ // The accessibility focus didn't handle the event, so clear
+ // the flag and do a normal dispatch to all children.
+ ev.setTargetAccessibilityFocus(false);
}
if (preorderedList != null) preorderedList.clear();
}
@@ -2803,6 +2846,34 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return buildOrderedChildList();
}
+ /**
+ * Finds the child which has accessibility focus.
+ *
+ * @return The child that has focus.
+ */
+ private View findChildWithAccessibilityFocus() {
+ ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot == null) {
+ return null;
+ }
+
+ View current = viewRoot.getAccessibilityFocusedHost();
+ if (current == null) {
+ return null;
+ }
+
+ ViewParent parent = current.getParent();
+ while (parent instanceof View) {
+ if (parent == this) {
+ return current;
+ }
+ current = (View) parent;
+ parent = current.getParent();
+ }
+
+ return null;
+ }
+
/**
* Resets all touch state in preparation for a new cycle.
*/
@@ -3257,9 +3328,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
break;
}
default:
- throw new IllegalStateException("descendant focusability must be "
- + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
- + "but is " + descendantFocusability);
+ throw new IllegalStateException(
+ "descendant focusability must be one of FOCUS_BEFORE_DESCENDANTS,"
+ + " FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS but is "
+ + descendantFocusability);
}
if (result && !isLayoutValid() && ((mPrivateFlags & PFLAG_WANTS_FOCUS) == 0)) {
mPrivateFlags |= PFLAG_WANTS_FOCUS;
@@ -4925,7 +4997,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
- throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
+ throw new IllegalArgumentException(
+ "generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ed40483be337..b860bac0d001 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -21,7 +21,6 @@ import static android.view.Display.INVALID_DISPLAY;
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;
@@ -4617,6 +4616,9 @@ public final class ViewRootImpl implements ViewParent,
}
void dispatchDetachedFromWindow() {
+ // Make sure we free-up insets resources if view never received onWindowFocusLost()
+ // because of a die-signal
+ mInsetsController.onWindowFocusLost();
mFirstInputStage.onDetachedFromWindow();
if (mView != null && mView.mAttachInfo != null) {
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index f7ca3c2b7ddf..90a80cefc54d 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONT
import android.annotation.NonNull;
import android.os.Handler;
+import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
@@ -236,4 +237,16 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host {
}
return 0;
}
+
+ @Override
+ public IBinder getWindowToken() {
+ if (mViewRoot == null) {
+ return null;
+ }
+ final View view = mViewRoot.getView();
+ if (view == null) {
+ return null;
+ }
+ return view.getWindowToken();
+ }
}
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index 68943bf2a83a..32b9cf7cdbb0 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -73,6 +73,8 @@ public final class AutofillId implements Parcelable {
}
/** @hide */
+ @NonNull
+ @TestApi
public static AutofillId withoutSession(@NonNull AutofillId id) {
final int flags = id.mFlags & ~FLAG_HAS_SESSION;
final long virtualChildId =
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 477dd1d13295..aedb59bfee42 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -19,6 +19,9 @@ package android.view.inputmethod;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR;
+import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR;
+
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -538,6 +541,19 @@ public final class InputMethodManager {
return servedView.hasWindowFocus() || isAutofillUIShowing(servedView);
}
+ /**
+ * Reports whether the IME is currently perceptible or not, according to the leash applied by
+ * {@link android.view.WindowInsetsController}.
+ * @hide
+ */
+ public void reportPerceptible(IBinder windowToken, boolean perceptible) {
+ try {
+ mService.reportPerceptible(windowToken, perceptible);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private final class DelegateImpl implements
ImeFocusController.InputMethodManagerDelegate {
/**
@@ -622,8 +638,11 @@ public final class InputMethodManager {
Log.v(TAG, "Reporting focus gain, without startInput"
+ ", nextFocusIsServedView=" + nextFocusIsServedView);
}
+ final int startInputReason =
+ nextFocusIsServedView ? WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR
+ : WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR;
mService.startInputOrWindowGainedFocus(
- StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
+ startInputReason, mClient,
focusedView.getWindowToken(), startInputFlags, softInputMode,
windowFlags,
nextFocusIsServedView ? mCurrentTextBoxAttribute : null,
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 51d37a53f21f..07a721f5a9c9 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -6354,6 +6354,8 @@ public class Editor {
// The offsets of that last touch down event. Remembered to start selection there.
private int mMinTouchOffset, mMaxTouchOffset;
+ private boolean mGestureStayedInTapRegion;
+
// Where the user first starts the drag motion.
private int mStartOffset = -1;
@@ -6460,8 +6462,10 @@ public class Editor {
eventX, eventY);
// Double tap detection
- if (mTouchState.isMultiTapInSameArea() && (isMouse
- || mTouchState.isOnHandle() || isPositionOnText(eventX, eventY))) {
+ if (mGestureStayedInTapRegion
+ && mTouchState.isMultiTapInSameArea()
+ && (isMouse || isPositionOnText(eventX, eventY)
+ || mTouchState.isOnHandle())) {
if (TextView.DEBUG_CURSOR) {
logCursor("SelectionModifierCursorController: onTouchEvent",
"ACTION_DOWN: select and start drag");
@@ -6473,6 +6477,7 @@ public class Editor {
}
mDiscardNextActionUp = true;
}
+ mGestureStayedInTapRegion = true;
mHaventMovedEnoughToStartDrag = true;
}
break;
@@ -6488,6 +6493,14 @@ public class Editor {
break;
case MotionEvent.ACTION_MOVE:
+ if (mGestureStayedInTapRegion) {
+ final ViewConfiguration viewConfig = ViewConfiguration.get(
+ mTextView.getContext());
+ mGestureStayedInTapRegion = EditorTouchState.isDistanceWithin(
+ mTouchState.getLastDownX(), mTouchState.getLastDownY(),
+ eventX, eventY, viewConfig.getScaledDoubleTapTouchSlop());
+ }
+
if (mHaventMovedEnoughToStartDrag) {
mHaventMovedEnoughToStartDrag = !mTouchState.isMovedEnoughForDrag();
}
diff --git a/core/java/android/widget/inline/InlineContentView.java b/core/java/android/widget/inline/InlineContentView.java
index 8ca218c1d1a7..1b666aa67e90 100644
--- a/core/java/android/widget/inline/InlineContentView.java
+++ b/core/java/android/widget/inline/InlineContentView.java
@@ -18,17 +18,22 @@ package android.widget.inline;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.Context;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
+import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver.OnPreDrawListener;
+import android.view.ViewTreeObserver;
+import java.lang.ref.WeakReference;
import java.util.function.Consumer;
/**
@@ -87,8 +92,10 @@ public class InlineContentView extends ViewGroup {
*
* @hide
*/
+ @TestApi
public interface SurfacePackageUpdater {
+
/**
* Called when the previous surface package is released due to view being detached
* from the window.
@@ -100,14 +107,16 @@ public class InlineContentView extends ViewGroup {
*
* @param consumer consumes the updated surface package.
*/
- void getSurfacePackage(Consumer<SurfaceControlViewHost.SurfacePackage> consumer);
+ void getSurfacePackage(@NonNull Consumer<SurfaceControlViewHost.SurfacePackage> consumer);
}
@NonNull
private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
- mSurfaceControlCallback.onCreated(mSurfaceView.getSurfaceControl());
+ final SurfaceControl surfaceControl = mSurfaceView.getSurfaceControl();
+ surfaceControl.addOnReparentListener(mOnReparentListener);
+ mSurfaceControlCallback.onCreated(surfaceControl);
}
@Override
@@ -118,7 +127,36 @@ public class InlineContentView extends ViewGroup {
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
- mSurfaceControlCallback.onDestroyed(mSurfaceView.getSurfaceControl());
+ final SurfaceControl surfaceControl = mSurfaceView.getSurfaceControl();
+ surfaceControl.removeOnReparentListener(mOnReparentListener);
+ mSurfaceControlCallback.onDestroyed(surfaceControl);
+ }
+ };
+
+ @NonNull
+ private final SurfaceControl.OnReparentListener mOnReparentListener =
+ new SurfaceControl.OnReparentListener() {
+ @Override
+ public void onReparent(SurfaceControl.Transaction transaction,
+ SurfaceControl parent) {
+ final View parentSurfaceOwnerView = (parent != null)
+ ? parent.getLocalOwnerView() : null;
+ if (parentSurfaceOwnerView instanceof SurfaceView) {
+ mParentSurfaceOwnerView = new WeakReference<>(
+ (SurfaceView) parentSurfaceOwnerView);
+ } else {
+ mParentSurfaceOwnerView = null;
+ }
+ }
+ };
+
+ @NonNull
+ private final ViewTreeObserver.OnDrawListener mOnDrawListener =
+ new ViewTreeObserver.OnDrawListener() {
+ @Override
+ public void onDraw() {
+ computeParentPositionAndScale();
+ mSurfaceView.setVisibility(VISIBLE);
}
};
@@ -126,21 +164,20 @@ public class InlineContentView extends ViewGroup {
private final SurfaceView mSurfaceView;
@Nullable
+ private WeakReference<SurfaceView> mParentSurfaceOwnerView;
+
+ @Nullable
+ private int[] mParentPosition;
+
+ @Nullable
+ private PointF mParentScale;
+
+ @Nullable
private SurfaceControlCallback mSurfaceControlCallback;
@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
@@ -164,6 +201,7 @@ public class InlineContentView extends ViewGroup {
public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
+ mSurfaceView.setEnableSurfaceClipping(true);
}
/**
@@ -177,6 +215,12 @@ public class InlineContentView extends ViewGroup {
return mSurfaceView.getSurfaceControl();
}
+ @Override
+ public void setClipBounds(Rect clipBounds) {
+ super.setClipBounds(clipBounds);
+ mSurfaceView.setClipBounds(clipBounds);
+ }
+
/**
* @inheritDoc
* @hide
@@ -184,10 +228,33 @@ public class InlineContentView extends ViewGroup {
public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mSurfaceView = new SurfaceView(context, attrs, defStyleAttr, defStyleRes);
+ mSurfaceView = new SurfaceView(context, attrs, defStyleAttr, defStyleRes) {
+ @Override
+ protected void onSetSurfacePositionAndScaleRT(
+ @NonNull SurfaceControl.Transaction transaction,
+ @NonNull SurfaceControl surface, int positionLeft, int positionTop,
+ float postScaleX, float postScaleY) {
+ // If we have a parent position, we need to make our coordinates relative
+ // to the parent in the rendering space.
+ if (mParentPosition != null) {
+ positionLeft = (int) ((positionLeft - mParentPosition[0]) / mParentScale.x);
+ positionTop = (int) ((positionTop - mParentPosition[1]) / mParentScale.y);
+ }
+
+ // Any scaling done to the parent or its predecessors would be applied
+ // via the surfaces parent -> child relation, so we only propagate any
+ // scaling set on the InlineContentView itself.
+ postScaleX = InlineContentView.this.getScaleX();
+ postScaleY = InlineContentView.this.getScaleY();
+
+ super.onSetSurfacePositionAndScaleRT(transaction, surface, positionLeft,
+ positionTop, postScaleX, postScaleY);
+ }
+ };
mSurfaceView.setZOrderOnTop(true);
mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
addView(mSurfaceView);
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
/**
@@ -195,6 +262,7 @@ public class InlineContentView extends ViewGroup {
*
* @hide
*/
+ @TestApi
public void setChildSurfacePackageUpdater(
@Nullable SurfacePackageUpdater surfacePackageUpdater) {
mSurfacePackageUpdater = surfacePackageUpdater;
@@ -213,8 +281,9 @@ public class InlineContentView extends ViewGroup {
}
});
}
- mSurfaceView.setVisibility(VISIBLE);
- getViewTreeObserver().addOnPreDrawListener(mDrawListener);
+
+ mSurfaceView.setVisibility(getVisibility());
+ getViewTreeObserver().addOnDrawListener(mOnDrawListener);
}
@Override
@@ -224,7 +293,9 @@ public class InlineContentView extends ViewGroup {
if (mSurfacePackageUpdater != null) {
mSurfacePackageUpdater.onSurfacePackageReleased();
}
- getViewTreeObserver().removeOnPreDrawListener(mDrawListener);
+
+ getViewTreeObserver().removeOnDrawListener(mOnDrawListener);
+ mSurfaceView.setVisibility(View.GONE);
}
@Override
@@ -271,4 +342,67 @@ public class InlineContentView extends ViewGroup {
public boolean setZOrderedOnTop(boolean onTop) {
return mSurfaceView.setZOrderedOnTop(onTop, /*allowDynamicChange*/ true);
}
+
+
+ private void computeParentPositionAndScale() {
+ boolean contentPositionOrScaleChanged = false;
+
+ // This method can be called on the UI or render thread but for the cases
+ // it is called these threads are not running concurrently, so no need to lock.
+ final SurfaceView parentSurfaceOwnerView = (mParentSurfaceOwnerView != null)
+ ? mParentSurfaceOwnerView.get() : null;
+
+ if (parentSurfaceOwnerView != null) {
+ if (mParentPosition == null) {
+ mParentPosition = new int[2];
+ }
+ final int oldParentPositionX = mParentPosition[0];
+ final int oldParentPositionY = mParentPosition[1];
+ parentSurfaceOwnerView.getLocationInSurface(mParentPosition);
+ if (oldParentPositionX != mParentPosition[0]
+ || oldParentPositionY != mParentPosition[1]) {
+ contentPositionOrScaleChanged = true;
+ }
+
+ if (mParentScale == null) {
+ mParentScale = new PointF();
+ }
+
+ final float lastParentSurfaceWidth = parentSurfaceOwnerView
+ .getSurfaceRenderPosition().width();
+ final float oldParentScaleX = mParentScale.x;
+ if (lastParentSurfaceWidth > 0) {
+ mParentScale.x = lastParentSurfaceWidth /
+ (float) parentSurfaceOwnerView.getWidth();
+ } else {
+ mParentScale.x = 1.0f;
+ }
+ if (!contentPositionOrScaleChanged
+ && Float.compare(oldParentScaleX, mParentScale.x) != 0) {
+ contentPositionOrScaleChanged = true;
+ }
+
+ final float lastParentSurfaceHeight = parentSurfaceOwnerView
+ .getSurfaceRenderPosition().height();
+ final float oldParentScaleY = mParentScale.y;
+ if (lastParentSurfaceHeight > 0) {
+ mParentScale.y = lastParentSurfaceHeight
+ / (float) parentSurfaceOwnerView.getHeight();
+ } else {
+ mParentScale.y = 1.0f;
+ }
+ if (!contentPositionOrScaleChanged
+ && Float.compare(oldParentScaleY, mParentScale.y) != 0) {
+ contentPositionOrScaleChanged = true;
+ }
+ } else if (mParentPosition != null || mParentScale != null) {
+ contentPositionOrScaleChanged = true;
+ mParentPosition = null;
+ mParentScale = null;
+ }
+
+ if (contentPositionOrScaleChanged) {
+ mSurfaceView.requestUpdateSurfacePositionAndScale();
+ }
+ }
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index dc4c8fd76e8e..a30c3c52f42c 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -691,8 +691,14 @@ public class ChooserActivity extends ResolverActivity implements
mPinnedSharedPrefs = getPinnedSharedPrefs(this);
pa = intent.getParcelableArrayExtra(Intent.EXTRA_EXCLUDE_COMPONENTS);
+
+
+ // Exclude out Nearby from main list if chip is present, to avoid duplication
+ ComponentName nearbySharingComponent = getNearbySharingComponent();
+ boolean hasNearby = nearbySharingComponent != null;
+
if (pa != null) {
- ComponentName[] names = new ComponentName[pa.length];
+ ComponentName[] names = new ComponentName[pa.length + (hasNearby ? 1 : 0)];
for (int i = 0; i < pa.length; i++) {
if (!(pa[i] instanceof ComponentName)) {
Log.w(TAG, "Filtered component #" + i + " not a ComponentName: " + pa[i]);
@@ -701,7 +707,14 @@ public class ChooserActivity extends ResolverActivity implements
}
names[i] = (ComponentName) pa[i];
}
+ if (hasNearby) {
+ names[names.length - 1] = nearbySharingComponent;
+ }
+
mFilteredComponentNames = names;
+ } else if (hasNearby) {
+ mFilteredComponentNames = new ComponentName[1];
+ mFilteredComponentNames[0] = nearbySharingComponent;
}
pa = intent.getParcelableArrayExtra(Intent.EXTRA_CHOOSER_TARGETS);
@@ -1004,11 +1017,17 @@ public class ChooserActivity extends ResolverActivity implements
/**
* Update UI to reflect changes in data.
- * <p>If {@code listAdapter} is {@code null}, both profile list adapters are updated.
+ * <p>If {@code listAdapter} is {@code null}, both profile list adapters are updated if
+ * available.
*/
private void handlePackagesChanged(@Nullable ResolverListAdapter listAdapter) {
+ // Refresh pinned items
+ mPinnedSharedPrefs = getPinnedSharedPrefs(this);
if (listAdapter == null) {
mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
+ if (mChooserMultiProfilePagerAdapter.getCount() > 1) {
+ mChooserMultiProfilePagerAdapter.getInactiveListAdapter().handlePackagesChanged();
+ }
} else {
listAdapter.handlePackagesChanged();
}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index e614a0eb996b..51e56b7fca43 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -36,10 +36,10 @@ interface IAppOpsService {
// and not be reordered
int checkOperation(int code, int uid, String packageName);
int noteOperation(int code, int uid, String packageName, @nullable String attributionTag,
- boolean shouldCollectAsyncNotedOp, String message);
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
int startOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String attributionTag, boolean startIfModeDefault,
- boolean shouldCollectAsyncNotedOp, String message);
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
@UnsupportedAppUsage
void finishOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String attributionTag);
@@ -54,7 +54,8 @@ interface IAppOpsService {
int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
String proxiedAttributionTag, int proxyUid, String proxyPackageName,
- String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message);
+ String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
+ boolean shouldCollectMessage);
// Remaining methods are only used in Java.
int checkPackage(int uid, String packageName);
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index 6f7695ce8c34..ca0856238b90 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -26,6 +26,8 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
@@ -97,7 +99,10 @@ public class UnlaunchableAppActivity extends Activity
@Override
public void onClick(DialogInterface dialog, int which) {
if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE && which == DialogInterface.BUTTON_POSITIVE) {
- UserManager.get(this).requestQuietModeEnabled(false, UserHandle.of(mUserId), mTarget);
+ UserManager userManager = UserManager.get(this);
+ new Handler(Looper.getMainLooper()).post(
+ () -> userManager.requestQuietModeEnabled(
+ /* enableQuietMode= */ false, UserHandle.of(mUserId), mTarget));
}
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
index a660493f4613..085cdfcf9462 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -46,8 +46,10 @@ public final class InputMethodDebug {
return "UNSPECIFIED";
case StartInputReason.WINDOW_FOCUS_GAIN:
return "WINDOW_FOCUS_GAIN";
- case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY:
- return "WINDOW_FOCUS_GAIN_REPORT_ONLY";
+ case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR:
+ return "WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR";
+ case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR:
+ return "WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR";
case StartInputReason.APP_CALLED_RESTART_INPUT_API:
return "APP_CALLED_RESTART_INPUT_API";
case StartInputReason.CHECK_FOCUS:
diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
index 79397b81ace7..4b968b45f122 100644
--- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
+++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
@@ -46,7 +46,8 @@ import java.lang.annotation.Retention;
SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE,
SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME,
SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED,
- SoftInputShowHideReason.HIDE_RECENTS_ANIMATION})
+ SoftInputShowHideReason.HIDE_RECENTS_ANIMATION,
+ SoftInputShowHideReason.HIDE_BUBBLES})
public @interface SoftInputShowHideReason {
/** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
int SHOW_SOFT_INPUT = 0;
@@ -140,4 +141,10 @@ public @interface SoftInputShowHideReason {
* intercept touch from app window.
*/
int HIDE_RECENTS_ANIMATION = 18;
+
+ /**
+ * Hide soft input when {@link com.android.systemui.bubbles.BubbleController} is expanding,
+ * switching, or collapsing Bubbles.
+ */
+ int HIDE_BUBBLES = 19;
}
diff --git a/core/java/com/android/internal/inputmethod/StartInputReason.java b/core/java/com/android/internal/inputmethod/StartInputReason.java
index a4eaa21538f7..946ce858c12d 100644
--- a/core/java/com/android/internal/inputmethod/StartInputReason.java
+++ b/core/java/com/android/internal/inputmethod/StartInputReason.java
@@ -30,7 +30,8 @@ import java.lang.annotation.Retention;
@IntDef(value = {
StartInputReason.UNSPECIFIED,
StartInputReason.WINDOW_FOCUS_GAIN,
- StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY,
+ StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR,
+ StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR,
StartInputReason.APP_CALLED_RESTART_INPUT_API,
StartInputReason.CHECK_FOCUS,
StartInputReason.BOUND_TO_IMMS,
@@ -49,45 +50,50 @@ public @interface StartInputReason {
*/
int WINDOW_FOCUS_GAIN = 1;
/**
+ * {@link android.view.Window} gained focus and the focused view is same as current served
+ * view and its input connection remains. {@link android.view.inputmethod.InputMethodManager}
+ * just reports this window focus change event to sync IME input target for system.
+ */
+ int WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR = 2;
+ /**
* {@link android.view.Window} gained focus but there is no {@link android.view.View} that is
- * eligible to have IME focus, or the focused view is same as current served view and its
- * input connection remains. {@link android.view.inputmethod.InputMethodManager} just reports
- * this window focus change event to sync IME input target for system.
+ * eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports
+ * this window focus change event for logging.
*/
- int WINDOW_FOCUS_GAIN_REPORT_ONLY = 2;
+ int WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR = 3;
/**
* {@link android.view.inputmethod.InputMethodManager#restartInput(android.view.View)} is
* either explicitly called by the application or indirectly called by some Framework class
* (e.g. {@link android.widget.EditText}).
*/
- int APP_CALLED_RESTART_INPUT_API = 3;
+ int APP_CALLED_RESTART_INPUT_API = 4;
/**
* {@link android.view.View} requested a new connection because of view focus change.
*/
- int CHECK_FOCUS = 4;
+ int CHECK_FOCUS = 5;
/**
* {@link android.view.inputmethod.InputMethodManager} is responding to
* {@link com.android.internal.view.IInputMethodClient#onBindMethod}.
*/
- int BOUND_TO_IMMS = 5;
+ int BOUND_TO_IMMS = 6;
/**
* {@link android.view.inputmethod.InputMethodManager} is responding to
* {@link com.android.internal.view.IInputMethodClient#onUnbindMethod}.
*/
- int UNBOUND_FROM_IMMS = 6;
+ int UNBOUND_FROM_IMMS = 7;
/**
* {@link android.view.inputmethod.InputMethodManager} is responding to
* {@link com.android.internal.view.IInputMethodClient#setActive}.
*/
- int ACTIVATED_BY_IMMS = 7;
+ int ACTIVATED_BY_IMMS = 8;
/**
* {@link android.view.inputmethod.InputMethodManager} is responding to
* {@link com.android.internal.view.IInputMethodClient#setActive}.
*/
- int DEACTIVATED_BY_IMMS = 8;
+ int DEACTIVATED_BY_IMMS = 9;
/**
* {@link com.android.server.inputmethod.InputMethodManagerService} is responding to
* {@link com.android.internal.view.IInputSessionCallback#sessionCreated}.
*/
- int SESSION_CREATED_BY_IME = 9;
+ int SESSION_CREATED_BY_IME = 10;
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index c32082418bc5..4999ec055608 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -79,6 +79,7 @@ interface IStatusBarService
void onNotificationSettingsViewed(String key);
void onNotificationBubbleChanged(String key, boolean isBubble, int flags);
void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed);
+ void hideCurrentInputMethodForBubbles();
void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
void clearInlineReplyUriPermissions(String key);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index d22f94213338..8ec51b89d240 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -72,5 +72,6 @@ interface IInputMethodManager {
void reportActivityView(in IInputMethodClient parentClient, int childDisplayId,
in float[] matrixValues);
+ oneway void reportPerceptible(in IBinder windowToken, boolean perceptible);
void removeImeSurface();
}
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 5d4407bf8370..0791ed3c42ec 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -197,7 +197,6 @@ public class ConversationLayout extends FrameLayout
super.onFinishInflate();
mMessagingLinearLayout = findViewById(R.id.notification_messaging);
mActions = findViewById(R.id.actions);
- mMessagingLinearLayout.setMessagingLayout(this);
mImageMessageContainer = findViewById(R.id.conversation_image_message_container);
// We still want to clip, but only on the top, since views can temporarily out of bounds
// during transitions.
@@ -1305,8 +1304,10 @@ public class ConversationLayout extends FrameLayout
if (expandable) {
mExpandButtonContainer.setVisibility(VISIBLE);
mExpandButtonInnerContainer.setOnClickListener(onClickListener);
+ mConversationIconContainer.setOnClickListener(onClickListener);
} else {
mExpandButtonContainer.setVisibility(GONE);
+ mConversationIconContainer.setOnClickListener(null);
}
updateContentEndPaddings();
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index a162e4e10c71..27cd6e13d86c 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -124,7 +124,6 @@ public class MessagingLayout extends FrameLayout
protected void onFinishInflate() {
super.onFinishInflate();
mMessagingLinearLayout = findViewById(R.id.notification_messaging);
- mMessagingLinearLayout.setMessagingLayout(this);
// We still want to clip, but only on the top, since views can temporarily out of bounds
// during transitions.
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 4ee647a42116..7cfd46c880fc 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -24,6 +24,7 @@ import android.util.AttributeSet;
import android.view.RemotableViewMethod;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.widget.RemoteViews;
import com.android.internal.R;
@@ -43,8 +44,6 @@ public class MessagingLinearLayout extends ViewGroup {
private int mMaxDisplayedLines = Integer.MAX_VALUE;
- private IMessagingLayout mMessagingLayout;
-
public MessagingLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -292,12 +291,19 @@ public class MessagingLinearLayout extends ViewGroup {
mMaxDisplayedLines = numberLines;
}
- public void setMessagingLayout(IMessagingLayout layout) {
- mMessagingLayout = layout;
- }
-
public IMessagingLayout getMessagingLayout() {
- return mMessagingLayout;
+ View view = this;
+ while (true) {
+ ViewParent p = view.getParent();
+ if (p instanceof View) {
+ view = (View) p;
+ if (view instanceof IMessagingLayout) {
+ return (IMessagingLayout) view;
+ }
+ } else {
+ return null;
+ }
+ }
}
@Override
diff --git a/core/proto/android/stats/connectivity/tethering.proto b/core/proto/android/stats/connectivity/tethering.proto
index 6303b7d1870b..13f0b8c44fb5 100644
--- a/core/proto/android/stats/connectivity/tethering.proto
+++ b/core/proto/android/stats/connectivity/tethering.proto
@@ -87,7 +87,7 @@ enum UpstreamType {
enum UserType {
// Unknown.
- USER_UNKOWNN = 0;
+ USER_UNKNOWN = 0;
// Settings.
USER_SETTINGS = 1;
// System UI.
diff --git a/core/res/res/drawable/chooser_action_button_bg.xml b/core/res/res/drawable/chooser_action_button_bg.xml
index a434c0b9b6a9..0dd9e9c7cd98 100644
--- a/core/res/res/drawable/chooser_action_button_bg.xml
+++ b/core/res/res/drawable/chooser_action_button_bg.xml
@@ -25,8 +25,8 @@
<shape android:shape="rectangle">
<corners android:radius="16dp"></corners>
<stroke android:width="1dp"
- android:color="?attr/textColorSecondary" />
- <solid android:color="?attr/colorBackground" />
+ android:color="?attr/opacityListDivider" />
+ <solid android:color="?attr/colorBackgroundFloating" />
</shape>
</inset>
</item>
diff --git a/core/res/res/layout/chooser_action_button.xml b/core/res/res/layout/chooser_action_button.xml
index 119b2e90292d..6af7937960f0 100644
--- a/core/res/res/layout/chooser_action_button.xml
+++ b/core/res/res/layout/chooser_action_button.xml
@@ -19,12 +19,12 @@
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:drawablePadding="8dp"
- android:textColor="?android:textColorSecondary"
+ android:textColor="?android:textColorPrimary"
android:textSize="12sp"
android:maxWidth="192dp"
android:singleLine="true"
android:clickable="true"
android:background="@drawable/chooser_action_button_bg"
- android:drawableTint="?android:attr/colorControlNormal"
+ android:drawableTint="@color/chooser_chip_icon"
android:drawableTintMode="src_in"
/>
diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml
index 139185f98b69..82e99e6419b6 100644
--- a/core/res/res/layout/notification_template_material_conversation.xml
+++ b/core/res/res/layout/notification_template_material_conversation.xml
@@ -139,7 +139,7 @@
>
<TextView
android:id="@+id/conversation_text"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin"
android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index f20470f5bcad..5c101888aff8 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1981,9 +1981,9 @@
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"توسيع"</string>
<string name="expand_button_content_description_expanded" msgid="7484217944948667489">"تصغير"</string>
<string name="expand_action_accessibility" msgid="1947657036871746627">"تبديل التوسيع"</string>
- <string name="usb_midi_peripheral_name" msgid="490523464968655741">"‏منفذ الأجهزة الطرفية المزودة بكابل USB ونظام التشغيل Android"</string>
+ <string name="usb_midi_peripheral_name" msgid="490523464968655741">"‏منفذ الأجهزة الملحقة المزودة بكابل USB ونظام التشغيل Android"</string>
<string name="usb_midi_peripheral_manufacturer_name" msgid="7557148557088787741">"Android"</string>
- <string name="usb_midi_peripheral_product_name" msgid="2836276258480904434">"‏منفذ الأجهزة الطرفية المزودة بكابل USB"</string>
+ <string name="usb_midi_peripheral_product_name" msgid="2836276258480904434">"‏منفذ الأجهزة الملحقة المزودة بكابل USB"</string>
<string name="floating_toolbar_open_overflow_description" msgid="2260297653578167367">"خيارات أخرى"</string>
<string name="floating_toolbar_close_overflow_description" msgid="3949818077708138098">"إغلاق التجاوز"</string>
<string name="maximize_button_text" msgid="4258922519914732645">"تكبير"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 5da4183eb6d7..a4c1ba42377c 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1645,7 +1645,7 @@
<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>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Uključiti funkcije pristupačnosti?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ako nekoliko sekundi držite pritisnute obje tipke za jačinu zvuka, uključit ćete funkcije pristupačnosti. Ovo može uticati na način rada uređaja.\n\nTrenutne funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nOdabrane funkcije možete izmijeniti u odjeljku Postavke &gt; Pristupačnost."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ako nekoliko sekundi držite pritisnute obje tipke za jačinu zvuka, uključit ćete funkcije pristupačnosti. Ovo može uticati na način rada uređaja.\n\nTrenutne funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nOdabrane funkcije možete promijeniti u odjeljku Postavke &gt; Pristupačnost."</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">"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>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 3b7a6edb4783..3ce57233cc09 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1695,7 +1695,7 @@
<string name="color_inversion_feature_name" msgid="326050048927789012">"Převrácení barev"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Oprava barev"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> byla vypnuta."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Chcete-li používat službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tři sekundy podržte stisknutá obě tlačítka hlasitosti"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Určete, jakou funkci aktivujete klepnutím na tlačítko přístupnosti:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Určete, jakou funkci aktivujete pomocí gesta přístupnosti (přejetí dvěma prsty ze spodní části obrazovky nahoru):"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 946cb7d0939c..4d3ca94b9c91 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1792,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 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 779fdff59351..96a4b1a4b863 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -316,7 +316,7 @@
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Body sensors"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"access sensor data about your vital signs"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Retrieve window content"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspect the content of a window that you\'re interacting with."</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspect the content of a window you\'re interacting with."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Turn on Explore by Touch"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Tapped items will be spoken aloud and the screen can be explored using gestures."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Observe text that you type"</string>
@@ -1006,7 +1006,7 @@
<string name="hour" msgid="7796325297097314653">"hour"</string>
<string name="hours" msgid="8517014849629200683">"hours"</string>
<string name="minute" msgid="8369209540986467610">"min"</string>
- <string name="minutes" msgid="3456532942641808971">"mins"</string>
+ <string name="minutes" msgid="3456532942641808971">"Min."</string>
<string name="second" msgid="9210875257112211713">"sec"</string>
<string name="seconds" msgid="2175052687727971048">"secs"</string>
<string name="week" msgid="907127093960923779">"week"</string>
@@ -1649,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">"Color 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>
diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml
index 98fece3b3c6c..39cdce9cc46b 100644
--- a/core/res/res/values-night/colors.xml
+++ b/core/res/res/values-night/colors.xml
@@ -35,6 +35,7 @@
<color name="resolver_empty_state_text">#FFFFFF</color>
<color name="resolver_empty_state_icon">#FFFFFF</color>
+ <color name="chooser_chip_icon">#8AB4F8</color> <!-- Blue 300 -->
<color name="personal_apps_suspension_notification_color">#8AB4F8</color>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 8173d07fb4c4..bea530000b22 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1651,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 de cor"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolha um recurso a ser usado quando você toca no botão de acessibilidade:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolha um recurso para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com dois dedos):"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 8173d07fb4c4..bea530000b22 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1651,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 de cor"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
- <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
+ <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolha um recurso a ser usado quando você toca no botão de acessibilidade:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolha um recurso para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com dois dedos):"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index a4d60e6a25df..d04c6187d6c6 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -92,7 +92,7 @@
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"紧急回拨模式"</string>
<string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"移动数据状态"</string>
<string name="notification_channel_sms" msgid="1243384981025535724">"短信"</string>
- <string name="notification_channel_voice_mail" msgid="8457433203106654172">"语音邮件"</string>
+ <string name="notification_channel_voice_mail" msgid="8457433203106654172">"语音信息"</string>
<string name="notification_channel_wfc" msgid="9048240466765169038">"WLAN 通话"</string>
<string name="notification_channel_sim" msgid="5098802350325677490">"SIM 卡状态"</string>
<string name="notification_channel_sim_high_prio" msgid="642361929452850928">"高优先顺序 SIM 卡状态"</string>
@@ -958,7 +958,7 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"允许该应用修改您手机上存储的浏览器历史记录或浏览器书签。此权限可让该应用清除或修改浏览器数据。请注意:此权限可能不适用于第三方浏览器或具备网页浏览功能的其他应用。"</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"设置闹钟"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"允许应用在已安装的闹钟应用中设置闹钟。有些闹钟应用可能无法实现此功能。"</string>
- <string name="permlab_addVoicemail" msgid="4770245808840814471">"添加语音邮件"</string>
+ <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>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index c413f8b036d7..1242c6dc8217 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -230,6 +230,7 @@
<color name="resolver_text_color_secondary_dark">#ffC4C6C6</color>
<color name="resolver_empty_state_text">#FF202124</color>
<color name="resolver_empty_state_icon">#FF5F6368</color>
+ <color name="chooser_chip_icon">#FF1A73E8</color> <!-- Blue 600 -->
<!-- Color for personal app suspension notification button text and icon tint. -->
<color name="personal_apps_suspension_notification_color">#1A73E8</color>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2869021a8a72..e2fbbf46608f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3022,6 +3022,8 @@
<public type="id" name="accessibilitySystemActionTakeScreenshot" id="0x01020053" />
<public type="id" name="accessibilityActionImeEnter" id="0x01020054" />
+ <!-- @hide @TestApi -->
+ <public type="bool" name="config_assistantOnTopOfDream" id="0x01110005" />
<!-- ===============================================================
Resources added in version S of the platform
@@ -3054,7 +3056,7 @@
<!-- dimension definitions go here -->
</public-group>
- <public-group type="bool" first-id="0x01110005">
+ <public-group type="bool" first-id="0x01110006">
<!-- boolean definitions go here -->
</public-group>
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 8eca650398bf..a2b1e3d69cd2 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -234,6 +234,24 @@ public class InsetsAnimationControlImplTest {
verify(mMockListener).onFinished(mController);
}
+ @Test
+ public void testPerceptible_insets() {
+ mController.setInsetsAndAlpha(mController.getHiddenStateInsets(), 1f, 1f);
+ verify(mMockController).reportPerceptible(systemBars(), false);
+
+ mController.setInsetsAndAlpha(mController.getShownStateInsets(), 1f, 1f);
+ verify(mMockController).reportPerceptible(systemBars(), true);
+ }
+
+ @Test
+ public void testPerceptible_alpha() {
+ mController.setInsetsAndAlpha(mController.getShownStateInsets(), 0f, 1f);
+ verify(mMockController).reportPerceptible(systemBars(), false);
+
+ mController.setInsetsAndAlpha(mController.getShownStateInsets(), 1f, 1f);
+ verify(mMockController).reportPerceptible(systemBars(), true);
+ }
+
private void assertPosition(Matrix m, Rect original, Rect transformed) {
RectF rect = new RectF(original);
rect.offsetTo(0, 0);
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index bf7f339a8484..1b3272572db0 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -26,13 +26,11 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
import android.app.Instrumentation;
import android.content.Context;
@@ -135,37 +133,29 @@ public class InsetsSourceConsumerTest {
InsetsSourceConsumer consumer = new InsetsSourceConsumer(
ITYPE_IME, state, null, controller);
- when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
-
InsetsSource source = new InsetsSource(ITYPE_IME);
source.setFrame(0, 1, 2, 3);
- consumer.updateSource(new InsetsSource(source));
-
- when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER);
+ consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_NONE);
// While we're animating, updates are delayed
source.setFrame(4, 5, 6, 7);
- consumer.updateSource(new InsetsSource(source));
+ consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_IME).getFrame());
// Finish the animation, now the pending frame should be applied
- when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
assertTrue(consumer.notifyAnimationFinished());
assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
- when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER);
-
// Animating again, updates are delayed
source.setFrame(8, 9, 10, 11);
- consumer.updateSource(new InsetsSource(source));
+ consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
// Updating with the current frame triggers a different code path, verify this clears
// the pending 8, 9, 10, 11 frame:
source.setFrame(4, 5, 6, 7);
- consumer.updateSource(new InsetsSource(source));
+ consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
- when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
assertFalse(consumer.notifyAnimationFinished());
assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
}
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index eb6ee9525bb9..5f231ffe4786 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -157,7 +157,7 @@ IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
table_value->dataType = entry->type;
table_value->data = entry->value;
- return Result(ResTable_entry_handle::managed(table_entry));
+ return Result(ResTable_entry_handle::managed(table_entry, [](auto p) { free(p); }));
}
static bool is_word_aligned(const void* data) {
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 21be81cb85bd..e351a46d633a 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1601,8 +1601,8 @@ class ResTable_entry_handle {
entry_ = handle.entry_;
}
- inline static ResTable_entry_handle managed(ResTable_entry* entry) {
- return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry));
+ inline static ResTable_entry_handle managed(ResTable_entry* entry, void (*deleter)(void *)) {
+ return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, deleter));
}
inline static ResTable_entry_handle unmanaged(const ResTable_entry* entry) {
diff --git a/location/java/android/location/AbstractListenerManager.java b/location/java/android/location/AbstractListenerManager.java
index 36b86899f2d8..f5595e89b807 100644
--- a/location/java/android/location/AbstractListenerManager.java
+++ b/location/java/android/location/AbstractListenerManager.java
@@ -29,6 +29,8 @@ import android.util.ArrayMap;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -193,7 +195,7 @@ abstract class AbstractListenerManager<TRequest, TListener> {
protected abstract void unregisterService() throws RemoteException;
@Nullable
- protected TRequest merge(@NonNull TRequest[] requests) {
+ protected TRequest merge(@NonNull List<TRequest> requests) {
for (TRequest request : requests) {
Preconditions.checkArgument(request == null,
"merge() has to be overridden for non-null requests.");
@@ -221,9 +223,9 @@ abstract class AbstractListenerManager<TRequest, TListener> {
return mListeners.valueAt(0).getRequest();
}
- TRequest[] requests = (TRequest[]) new Object[mListeners.size()];
+ ArrayList<TRequest> requests = new ArrayList<>(mListeners.size());
for (int index = 0; index < mListeners.size(); index++) {
- requests[index] = mListeners.valueAt(index).getRequest();
+ requests.add(mListeners.valueAt(index).getRequest());
}
return merge(requests);
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 7d15bbd46697..f3c9e9435417 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -3030,14 +3030,14 @@ public class LocationManager {
@Override
@Nullable
- protected GnssRequest merge(@NonNull GnssRequest[] requests) {
- Preconditions.checkArgument(requests.length > 0);
+ protected GnssRequest merge(@NonNull List<GnssRequest> requests) {
+ Preconditions.checkArgument(!requests.isEmpty());
for (GnssRequest request : requests) {
if (request.isFullTracking()) {
return request;
}
}
- return requests[0];
+ return requests.get(0);
}
private class GnssMeasurementsListener extends IGnssMeasurementsListener.Stub {
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 2cca669a592b..00a4c7e19f34 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -448,8 +448,7 @@ public final class AudioDeviceInfo {
* Returns an array of supported encapsulation modes for the device.
*
* The array can include any of the {@code AudioTrack} encapsulation modes,
- * e.g. {@link AudioTrack#ENCAPSULATION_MODE_NONE},
- * or {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM}.
+ * e.g. {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM}.
*
* @return An array of supported encapsulation modes for the device. This
* may be an empty array if no encapsulation modes are supported.
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ea7a556f835b..3ac71b2cff1d 100755
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4599,6 +4599,12 @@ public class AudioManager {
/**
* @hide
+ * Volume behavior for an audio device that has no particular volume behavior set. Invalid as
+ * an argument to {@link #setDeviceVolumeBehavior(int, String, int)}.
+ */
+ public static final int DEVICE_VOLUME_BEHAVIOR_UNSET = -1;
+ /**
+ * @hide
* Volume behavior for an audio device where a software attenuation is applied
* @see #setDeviceVolumeBehavior(int, String, int)
*/
@@ -4647,6 +4653,18 @@ public class AudioManager {
@Retention(RetentionPolicy.SOURCE)
public @interface DeviceVolumeBehavior {}
+ /** @hide */
+ @IntDef({
+ DEVICE_VOLUME_BEHAVIOR_UNSET,
+ DEVICE_VOLUME_BEHAVIOR_VARIABLE,
+ DEVICE_VOLUME_BEHAVIOR_FULL,
+ DEVICE_VOLUME_BEHAVIOR_FIXED,
+ DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
+ DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeviceVolumeBehaviorState {}
+
/**
* @hide
* Throws IAE on an invalid volume behavior value
@@ -4713,7 +4731,7 @@ public class AudioManager {
* @return the volume behavior for the device
*/
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @DeviceVolumeBehavior int getDeviceVolumeBehavior(int deviceType,
+ public @DeviceVolumeBehaviorState int getDeviceVolumeBehavior(int deviceType,
@Nullable String deviceAddress) {
// verify arguments
AudioDeviceInfo.enforceValidAudioDeviceTypeOut(deviceType);
@@ -4728,8 +4746,8 @@ public class AudioManager {
* @return the volume behavior for the device
*/
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @DeviceVolumeBehavior int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device)
- {
+ public @DeviceVolumeBehaviorState int getDeviceVolumeBehavior(
+ @NonNull AudioDeviceAttributes device) {
// verify arguments (validity of device type is enforced in server)
Objects.requireNonNull(device);
// communicate with service
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 9f3fc5d94a98..1c0a526f536c 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -280,7 +280,7 @@ public class AudioTrack extends PlayerBase
/**
* Encapsulation metadata type for framework tuner information.
*
- * TODO(b/147778408) Link: Fill in Tuner API info.
+ * Refer to the Android Media TV Tuner API for details.
*/
public static final int ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER = 1;
diff --git a/media/java/android/media/IMediaRouter2.aidl b/media/java/android/media/IMediaRouter2.aidl
index ca14052c964f..fe15f0e67b1d 100644
--- a/media/java/android/media/IMediaRouter2.aidl
+++ b/media/java/android/media/IMediaRouter2.aidl
@@ -34,7 +34,8 @@ oneway interface IMediaRouter2 {
void notifySessionReleased(in RoutingSessionInfo sessionInfo);
/**
* Gets hints of the new session for the given route.
- * Call MediaRouterService#notifySessionHintsForCreatingSession to pass the result.
+ * Call MediaRouterService#requestCreateSessionWithRouter2 to pass the result.
*/
- void getSessionHintsForCreatingSession(long uniqueRequestId, in MediaRoute2Info route);
+ void requestCreateSessionByManager(long uniqueRequestId, in RoutingSessionInfo oldSession,
+ in MediaRoute2Info route);
}
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 52bac671cc6f..068f9689d06f 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -44,7 +44,7 @@ interface IMediaRouterService {
void requestSetVolume(IMediaRouterClient client, String routeId, int volume);
void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction);
- // Note: When changing this file, match the order of methods below with
+ // Note: When changing this file, match the order of methods below with
// MediaRouterService.java for readability.
// Methods for MediaRouter2
@@ -57,10 +57,9 @@ interface IMediaRouterService {
in RouteDiscoveryPreference preference);
void setRouteVolumeWithRouter2(IMediaRouter2 router, in MediaRoute2Info route, int volume);
- void requestCreateSessionWithRouter2(IMediaRouter2 router, int requestId,
- in MediaRoute2Info route, in @nullable Bundle sessionHints);
- void notifySessionHintsForCreatingSession(IMediaRouter2 router, long uniqueRequestId,
- in MediaRoute2Info route, in @nullable Bundle sessionHints);
+ void requestCreateSessionWithRouter2(IMediaRouter2 router, int requestId, long managerRequestId,
+ in RoutingSessionInfo oldSession, in MediaRoute2Info route,
+ in @nullable Bundle sessionHints);
void selectRouteWithRouter2(IMediaRouter2 router, String sessionId, in MediaRoute2Info route);
void deselectRouteWithRouter2(IMediaRouter2 router, String sessionId, in MediaRoute2Info route);
void transferToRouteWithRouter2(IMediaRouter2 router, String sessionId,
@@ -76,7 +75,7 @@ interface IMediaRouterService {
in MediaRoute2Info route, int volume);
void requestCreateSessionWithManager(IMediaRouter2Manager manager, int requestId,
- String packageName, in @nullable MediaRoute2Info route);
+ in RoutingSessionInfo oldSession, in @nullable MediaRoute2Info route);
void selectRouteWithManager(IMediaRouter2Manager manager, int requestId,
String sessionId, in MediaRoute2Info route);
void deselectRouteWithManager(IMediaRouter2Manager manager, int requestId,
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 62d76c0d2d58..0780c6875eb5 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2762,7 +2762,7 @@ final public class MediaCodec {
builder.append(hexdigits.charAt(key[i] & 0x0f));
}
builder.append("], iv [");
- for (int i = 0; i < key.length; i++) {
+ for (int i = 0; i < iv.length; i++) {
builder.append(hexdigits.charAt((iv[i] & 0xf0) >> 4));
builder.append(hexdigits.charAt(iv[i] & 0x0f));
}
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 8e95239a73f8..f22222d10ad8 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -36,7 +36,6 @@ import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -62,6 +61,11 @@ public final class MediaRouter2 {
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final Object sRouterLock = new Object();
+ // The maximum time for the old routing controller available after transfer.
+ private static final int TRANSFER_TIMEOUT_MS = 30_000;
+ // The manager request ID representing that no manager is involved.
+ private static final long MANAGER_REQUEST_ID_NONE = MediaRoute2ProviderService.REQUEST_ID_NONE;
+
@GuardedBy("sRouterLock")
private static MediaRouter2 sInstance;
@@ -80,7 +84,7 @@ public final class MediaRouter2 {
private final String mPackageName;
@GuardedBy("sRouterLock")
- final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
+ final Map<String, MediaRoute2Info> mRoutes = new ArrayMap<>();
final RoutingController mSystemController;
@@ -94,7 +98,7 @@ public final class MediaRouter2 {
@GuardedBy("sRouterLock")
private final Map<String, RoutingController> mNonSystemRoutingControllers = new ArrayMap<>();
- private final AtomicInteger mControllerCreationRequestCnt = new AtomicInteger(1);
+ private final AtomicInteger mNextRequestId = new AtomicInteger(1);
final Handler mHandler;
@GuardedBy("sRouterLock")
@@ -412,9 +416,16 @@ public final class MediaRouter2 {
return;
}
- final int requestId = mControllerCreationRequestCnt.getAndIncrement();
+ requestCreateController(controller, route, MANAGER_REQUEST_ID_NONE);
+ }
+
+ void requestCreateController(@NonNull RoutingController controller,
+ @NonNull MediaRoute2Info route, long managerRequestId) {
- ControllerCreationRequest request = new ControllerCreationRequest(requestId, route);
+ final int requestId = mNextRequestId.getAndIncrement();
+
+ ControllerCreationRequest request = new ControllerCreationRequest(requestId,
+ managerRequestId, route, controller);
mControllerCreationRequests.add(request);
OnGetControllerHintsListener listener = mOnGetControllerHintsListener;
@@ -433,11 +444,15 @@ public final class MediaRouter2 {
if (stub != null) {
try {
mMediaRouterService.requestCreateSessionWithRouter2(
- stub, requestId, route, controllerHints);
+ stub, requestId, managerRequestId,
+ controller.getRoutingSessionInfo(), route, controllerHints);
} catch (RemoteException ex) {
- Log.e(TAG, "transfer: Unable to request to create controller.", ex);
- mHandler.sendMessage(obtainMessage(MediaRouter2::createControllerOnHandler,
- MediaRouter2.this, requestId, null));
+ Log.e(TAG, "createControllerForTransfer: "
+ + "Failed to request for creating a controller.", ex);
+ mControllerCreationRequests.remove(request);
+ if (managerRequestId == MANAGER_REQUEST_ID_NONE) {
+ notifyTransferFailure(route);
+ }
}
}
}
@@ -463,7 +478,8 @@ public final class MediaRouter2 {
}
/**
- * Gets the list of currently non-released {@link RoutingController routing controllers}.
+ * Gets the list of currently active {@link RoutingController routing controllers} on which
+ * media can be played.
* <p>
* Note: The list returned here will never be empty. The first element in the list is
* always the {@link #getSystemController() system controller}.
@@ -554,13 +570,13 @@ public final class MediaRouter2 {
mShouldUpdateRoutes = true;
}
- if (addedRoutes.size() > 0) {
+ if (!addedRoutes.isEmpty()) {
notifyRoutesAdded(addedRoutes);
}
- if (removedRoutes.size() > 0) {
+ if (!removedRoutes.isEmpty()) {
notifyRoutesRemoved(removedRoutes);
}
- if (changedRoutes.size() > 0) {
+ if (!changedRoutes.isEmpty()) {
notifyRoutesChanged(changedRoutes);
}
@@ -582,7 +598,7 @@ public final class MediaRouter2 {
}
mShouldUpdateRoutes = true;
}
- if (addedRoutes.size() > 0) {
+ if (!addedRoutes.isEmpty()) {
notifyRoutesAdded(addedRoutes);
}
}
@@ -598,7 +614,7 @@ public final class MediaRouter2 {
}
mShouldUpdateRoutes = true;
}
- if (removedRoutes.size() > 0) {
+ if (!removedRoutes.isEmpty()) {
notifyRoutesRemoved(removedRoutes);
}
}
@@ -614,7 +630,7 @@ public final class MediaRouter2 {
}
mShouldUpdateRoutes = true;
}
- if (changedRoutes.size() > 0) {
+ if (!changedRoutes.isEmpty()) {
notifyRoutesChanged(changedRoutes);
}
}
@@ -635,44 +651,47 @@ public final class MediaRouter2 {
}
}
- if (matchingRequest != null) {
- mControllerCreationRequests.remove(matchingRequest);
-
- MediaRoute2Info requestedRoute = matchingRequest.mRoute;
-
- if (sessionInfo == null) {
- // TODO: We may need to distinguish between failure and rejection.
- // One way can be introducing 'reason'.
- notifyTransferFailure(requestedRoute);
- return;
- } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
- Log.w(TAG, "The session does not contain the requested route. "
- + "(requestedRouteId=" + requestedRoute.getId()
- + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
- + ")");
- notifyTransferFailure(requestedRoute);
- return;
- } else if (!TextUtils.equals(requestedRoute.getProviderId(),
- sessionInfo.getProviderId())) {
- Log.w(TAG, "The session's provider ID does not match the requested route's. "
- + "(requested route's providerId=" + requestedRoute.getProviderId()
- + ", actual providerId=" + sessionInfo.getProviderId()
- + ")");
- notifyTransferFailure(requestedRoute);
- return;
- }
+ if (matchingRequest == null) {
+ Log.w(TAG, "createControllerOnHandler: Ignoring an unknown request.");
+ return;
}
+ mControllerCreationRequests.remove(matchingRequest);
+ MediaRoute2Info requestedRoute = matchingRequest.mRoute;
+
+ // TODO: Notify the reason for failure.
if (sessionInfo == null) {
+ notifyTransferFailure(requestedRoute);
+ return;
+ } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
+ Log.w(TAG, "The session does not contain the requested route. "
+ + "(requestedRouteId=" + requestedRoute.getId()
+ + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
+ + ")");
+ notifyTransferFailure(requestedRoute);
+ return;
+ } else if (!TextUtils.equals(requestedRoute.getProviderId(),
+ sessionInfo.getProviderId())) {
+ Log.w(TAG, "The session's provider ID does not match the requested route's. "
+ + "(requested route's providerId=" + requestedRoute.getProviderId()
+ + ", actual providerId=" + sessionInfo.getProviderId()
+ + ")");
+ notifyTransferFailure(requestedRoute);
return;
}
- RoutingController oldController = getCurrentController();
- if (!oldController.releaseInternal(
- /* shouldReleaseSession= */ matchingRequest != null,
- /* shouldNotifyStop= */ false)) {
- // Could not release the controller since it was just released by other thread.
- oldController = getSystemController();
+ RoutingController oldController = matchingRequest.mOldController;
+ // When the old controller is released before transferred, treat it as a failure.
+ // This could also happen when transfer is requested twice or more.
+ if (!oldController.scheduleRelease()) {
+ Log.w(TAG, "createControllerOnHandler: "
+ + "Ignoring controller creation for released old controller. "
+ + "oldController=" + oldController);
+ if (!sessionInfo.isSystemSession()) {
+ new RoutingController(sessionInfo).release();
+ }
+ notifyTransferFailure(requestedRoute);
+ return;
}
RoutingController newController;
@@ -686,12 +705,7 @@ public final class MediaRouter2 {
}
}
- // Two controller can be same if stop() is called before the result of Cast -> Phone comes.
- if (oldController != newController) {
- notifyTransfer(oldController, newController);
- } else if (matchingRequest != null) {
- notifyTransferFailure(matchingRequest.mRoute);
- }
+ notifyTransfer(oldController, newController);
}
void updateControllerOnHandler(RoutingSessionInfo sessionInfo) {
@@ -736,10 +750,9 @@ public final class MediaRouter2 {
return;
}
- final String uniqueSessionId = sessionInfo.getId();
RoutingController matchingController;
synchronized (sRouterLock) {
- matchingController = mNonSystemRoutingControllers.get(uniqueSessionId);
+ matchingController = mNonSystemRoutingControllers.get(sessionInfo.getId());
}
if (matchingController == null) {
@@ -757,34 +770,23 @@ public final class MediaRouter2 {
return;
}
- matchingController.releaseInternal(
- /* shouldReleaseSession= */ false, /* shouldNotifyStop= */ true);
+ matchingController.releaseInternal(/* shouldReleaseSession= */ false);
}
- void onGetControllerHintsForCreatingSessionOnHandler(long uniqueRequestId,
- MediaRoute2Info route) {
- OnGetControllerHintsListener listener = mOnGetControllerHintsListener;
- Bundle controllerHints = null;
- if (listener != null) {
- controllerHints = listener.onGetControllerHints(route);
- if (controllerHints != null) {
- controllerHints = new Bundle(controllerHints);
+ void onRequestCreateControllerByManagerOnHandler(RoutingSessionInfo oldSession,
+ MediaRoute2Info route, long managerRequestId) {
+ RoutingController controller;
+ if (oldSession.isSystemSession()) {
+ controller = getSystemController();
+ } else {
+ synchronized (sRouterLock) {
+ controller = mNonSystemRoutingControllers.get(oldSession.getId());
}
}
-
- MediaRouter2Stub stub;
- synchronized (sRouterLock) {
- stub = mStub;
- }
- if (stub != null) {
- try {
- mMediaRouterService.notifySessionHintsForCreatingSession(
- stub, uniqueRequestId, route, controllerHints);
- } catch (RemoteException ex) {
- Log.e(TAG, "onGetControllerHintsForCreatingSessionOnHandler: Unable to notify "
- + " session hints for creating session.", ex);
- }
+ if (controller == null) {
+ return;
}
+ requestCreateController(controller, route, managerRequestId);
}
private List<MediaRoute2Info> filterRoutes(List<MediaRoute2Info> routes,
@@ -886,8 +888,13 @@ public final class MediaRouter2 {
/**
* Called when a media is transferred between two different routing controllers.
* This can happen by calling {@link #transferTo(MediaRoute2Info)}.
- * The {@code oldController} is released before this method is called, except for the
- * {@link #getSystemController() system controller}.
+ * <p> Override this to start playback with {@code newController}. You may want to get
+ * the status of the media that is being played with {@code oldController} and resume it
+ * continuously with {@code newController}.
+ * After this is called, any callbacks with {@code oldController} will not be invoked
+ * unless {@code oldController} is the {@link #getSystemController() system controller}.
+ * You need to {@link RoutingController#release() release} {@code oldController} before
+ * playing the media with {@code newController}.
*
* @param oldController the previous controller that controlled routing
* @param newController the new controller to control routing
@@ -906,16 +913,15 @@ public final class MediaRouter2 {
/**
* Called when a media routing stops. It can be stopped by a user or a provider.
* App should not continue playing media locally when this method is called.
- * The {@code oldController} is released before this method is called, except for the
- * {@link #getSystemController() system controller}.
+ * The {@code controller} is released before this method is called.
*
- * @param controller the controller that controlled the stopped media routing.
+ * @param controller the controller that controlled the stopped media routing
*/
public void onStop(@NonNull RoutingController controller) { }
}
/**
- * A listener interface to send an optional app-specific hints when creating the
+ * A listener interface to send optional app-specific hints when creating a
* {@link RoutingController}.
*/
public interface OnGetControllerHintsListener {
@@ -929,9 +935,9 @@ public final class MediaRouter2 {
* The method will be called on the same thread that calls
* {@link #transferTo(MediaRoute2Info)} or the main thread if it is requested by the system.
*
- * @param route The route to create controller with
+ * @param route the route to create a controller with
* @return An optional bundle of app-specific arguments to send to the provider,
- * or null if none. The contents of this bundle may affect the result of
+ * or {@code null} if none. The contents of this bundle may affect the result of
* controller creation.
* @see MediaRoute2ProviderService#onCreateSession(long, String, String, Bundle)
*/
@@ -944,10 +950,11 @@ public final class MediaRouter2 {
*/
public abstract static class ControllerCallback {
/**
- * Called when a controller is updated. (e.g., the selected routes of the
- * controller is changed or the volume of the controller is changed.)
+ * Called when a controller is updated. (e.g., when the selected routes of the
+ * controller is changed or when the volume of the controller is changed.)
*
- * @param controller the updated controller. Can be the system controller.
+ * @param controller the updated controller. It may be the
+ * {@link #getSystemController() system controller}.
* @see #getSystemController()
*/
public void onControllerUpdated(@NonNull RoutingController controller) { }
@@ -955,20 +962,28 @@ public final class MediaRouter2 {
/**
* A class to control media routing session in media route provider.
- * For example, selecting/deselecting/transferring routes to a session can be done through this
- * class. Instances are created by {@link #transferTo(MediaRoute2Info)}.
+ * For example, selecting/deselecting/transferring to routes of a session can be done through
+ * this. Instances are created when
+ * {@link TransferCallback#onTransfer(RoutingController, RoutingController)} is called,
+ * which is invoked after {@link #transferTo(MediaRoute2Info)} is called.
*/
public class RoutingController {
private final Object mControllerLock = new Object();
+ private static final int CONTROLLER_STATE_UNKNOWN = 0;
+ private static final int CONTROLLER_STATE_ACTIVE = 1;
+ private static final int CONTROLLER_STATE_RELEASING = 2;
+ private static final int CONTROLLER_STATE_RELEASED = 3;
+
@GuardedBy("mControllerLock")
private RoutingSessionInfo mSessionInfo;
@GuardedBy("mControllerLock")
- private volatile boolean mIsReleased;
+ private int mState;
RoutingController(@NonNull RoutingSessionInfo sessionInfo) {
mSessionInfo = sessionInfo;
+ mState = CONTROLLER_STATE_ACTIVE;
}
/**
@@ -982,7 +997,7 @@ public final class MediaRouter2 {
}
/**
- * Gets the original session id set by
+ * Gets the original session ID set by
* {@link RoutingSessionInfo.Builder#Builder(String, String)}.
*
* @hide
@@ -996,7 +1011,8 @@ public final class MediaRouter2 {
}
/**
- * @return the control hints used to control routing session if available.
+ * Gets the control hints used to control routing session if available.
+ * It is set by the media route provider.
*/
@Nullable
public Bundle getControlHints() {
@@ -1042,7 +1058,9 @@ public final class MediaRouter2 {
}
/**
- * Gets information about how volume is handled on the session.
+ * Gets the information about how volume is handled on the session.
+ * <p>Please note that you may not control the volume of the session even when
+ * you can control the volume of each selected route in the session.
*
* @return {@link MediaRoute2Info#PLAYBACK_VOLUME_FIXED} or
* {@link MediaRoute2Info#PLAYBACK_VOLUME_VARIABLE}
@@ -1067,8 +1085,8 @@ public final class MediaRouter2 {
* Gets the current volume of the session.
* <p>
* When it's available, it represents the volume of routing session, which is a group
- * of selected routes. To get the volume of a route,
- * use {@link MediaRoute2Info#getVolume()}.
+ * of selected routes. Use {@link MediaRoute2Info#getVolume()}
+ * to get the volume of a route,
* </p>
* @see MediaRoute2Info#getVolume()
*/
@@ -1087,7 +1105,7 @@ public final class MediaRouter2 {
*/
public boolean isReleased() {
synchronized (mControllerLock) {
- return mIsReleased;
+ return mState == CONTROLLER_STATE_RELEASED;
}
}
@@ -1099,8 +1117,8 @@ public final class MediaRouter2 {
* <p>
* The given route must satisfy all of the following conditions:
* <ul>
- * <li>ID should not be included in {@link #getSelectedRoutes()}</li>
- * <li>ID should be included in {@link #getSelectableRoutes()}</li>
+ * <li>It should not be included in {@link #getSelectedRoutes()}</li>
+ * <li>It should be included in {@link #getSelectableRoutes()}</li>
* </ul>
* If the route doesn't meet any of above conditions, it will be ignored.
*
@@ -1111,11 +1129,9 @@ public final class MediaRouter2 {
*/
public void selectRoute(@NonNull MediaRoute2Info route) {
Objects.requireNonNull(route, "route must not be null");
- synchronized (mControllerLock) {
- if (mIsReleased) {
- Log.w(TAG, "selectRoute: Called on released controller. Ignoring.");
- return;
- }
+ if (isReleased()) {
+ Log.w(TAG, "selectRoute: Called on released controller. Ignoring.");
+ return;
}
List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
@@ -1145,12 +1161,12 @@ public final class MediaRouter2 {
/**
* Deselects a route from the remote session. After a route is deselected, the media is
- * expected to be stopped on the deselected routes.
+ * expected to be stopped on the deselected route.
* <p>
* The given route must satisfy all of the following conditions:
* <ul>
- * <li>ID should be included in {@link #getSelectedRoutes()}</li>
- * <li>ID should be included in {@link #getDeselectableRoutes()}</li>
+ * <li>It should be included in {@link #getSelectedRoutes()}</li>
+ * <li>It should be included in {@link #getDeselectableRoutes()}</li>
* </ul>
* If the route doesn't meet any of above conditions, it will be ignored.
*
@@ -1160,11 +1176,9 @@ public final class MediaRouter2 {
*/
public void deselectRoute(@NonNull MediaRoute2Info route) {
Objects.requireNonNull(route, "route must not be null");
- synchronized (mControllerLock) {
- if (mIsReleased) {
- Log.w(TAG, "deselectRoute: called on released controller. Ignoring.");
- return;
- }
+ if (isReleased()) {
+ Log.w(TAG, "deselectRoute: called on released controller. Ignoring.");
+ return;
}
List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
@@ -1193,13 +1207,8 @@ public final class MediaRouter2 {
}
/**
- * Transfers to a given route for the remote session. The given route must satisfy
- * all of the following conditions:
- * <ul>
- * <li>ID should not be included in {@link RoutingSessionInfo#getSelectedRoutes()}</li>
- * <li>ID should be included in {@link RoutingSessionInfo#getTransferableRoutes()}</li>
- * </ul>
- * If the route doesn't meet any of above conditions, it will be ignored.
+ * Transfers to a given route for the remote session. The given route must be included
+ * in {@link RoutingSessionInfo#getTransferableRoutes()}.
*
* @see RoutingSessionInfo#getSelectedRoutes()
* @see RoutingSessionInfo#getTransferableRoutes()
@@ -1208,19 +1217,13 @@ public final class MediaRouter2 {
void transferToRoute(@NonNull MediaRoute2Info route) {
Objects.requireNonNull(route, "route must not be null");
synchronized (mControllerLock) {
- if (mIsReleased) {
+ if (isReleased()) {
Log.w(TAG, "transferToRoute: Called on released controller. Ignoring.");
return;
}
- if (mSessionInfo.getSelectedRoutes().contains(route.getId())) {
- Log.w(TAG, "Ignoring transferring to a route that is already added. "
- + "route=" + route);
- return;
- }
-
if (!mSessionInfo.getTransferableRoutes().contains(route.getId())) {
- Log.w(TAG, "Ignoring transferring to a non-transferrable route=" + route);
+ Log.w(TAG, "Ignoring transferring to a non-transferable route=" + route);
return;
}
}
@@ -1255,11 +1258,9 @@ public final class MediaRouter2 {
return;
}
- synchronized (mControllerLock) {
- if (mIsReleased) {
- Log.w(TAG, "setVolume: Called on released controller. Ignoring.");
- return;
- }
+ if (isReleased()) {
+ Log.w(TAG, "setVolume: Called on released controller. Ignoring.");
+ return;
}
MediaRouter2Stub stub;
synchronized (sRouterLock) {
@@ -1275,33 +1276,58 @@ public final class MediaRouter2 {
}
/**
- * Release this controller and corresponding session.
+ * Releases this controller and the corresponding session.
* Any operations on this controller after calling this method will be ignored.
* The devices that are playing media will stop playing it.
*/
- // TODO(b/157872573): Add tests using {@link MediaRouter2Manager#getActiveSessions()}.
public void release() {
- releaseInternal(/* shouldReleaseSession= */ true, /* shouldNotifyStop= */ true);
+ releaseInternal(/* shouldReleaseSession= */ true);
}
/**
- * Returns {@code true} when succeeded to release, {@code false} if the controller is
- * already released.
+ * Schedules release of the controller.
+ * @return {@code true} if it's successfully scheduled, {@code false} if it's already
+ * scheduled to be released or released.
*/
- boolean releaseInternal(boolean shouldReleaseSession, boolean shouldNotifyStop) {
+ boolean scheduleRelease() {
synchronized (mControllerLock) {
- if (mIsReleased) {
- Log.w(TAG, "releaseInternal: Called on released controller. Ignoring.");
+ if (mState != CONTROLLER_STATE_ACTIVE) {
return false;
}
- mIsReleased = true;
+ mState = CONTROLLER_STATE_RELEASING;
}
synchronized (sRouterLock) {
+ // It could happen if the controller is released by the another thread
+ // in between two locks
if (!mNonSystemRoutingControllers.remove(getId(), this)) {
- Log.w(TAG, "releaseInternal: Ignoring unknown controller.");
- return false;
+ // In that case, onStop isn't called so we return true to call onTransfer.
+ // It's also consistent with that the another thread acquires the lock later.
+ return true;
}
+ }
+
+ mHandler.postDelayed(this::release, TRANSFER_TIMEOUT_MS);
+
+ return true;
+ }
+
+ void releaseInternal(boolean shouldReleaseSession) {
+ boolean shouldNotifyStop;
+
+ synchronized (mControllerLock) {
+ if (mState == CONTROLLER_STATE_RELEASED) {
+ if (DEBUG) {
+ Log.d(TAG, "releaseInternal: Called on released controller. Ignoring.");
+ }
+ return;
+ }
+ shouldNotifyStop = (mState == CONTROLLER_STATE_ACTIVE);
+ mState = CONTROLLER_STATE_RELEASED;
+ }
+
+ synchronized (sRouterLock) {
+ mNonSystemRoutingControllers.remove(getId(), this);
if (shouldReleaseSession && mStub != null) {
try {
@@ -1326,7 +1352,6 @@ public final class MediaRouter2 {
mStub = null;
}
}
- return true;
}
@Override
@@ -1389,9 +1414,14 @@ public final class MediaRouter2 {
}
@Override
- boolean releaseInternal(boolean shouldReleaseSession, boolean shouldNotifyStop) {
+ boolean scheduleRelease() {
+ // SystemRoutingController can be always transferred
+ return true;
+ }
+
+ @Override
+ void releaseInternal(boolean shouldReleaseSession) {
// Do nothing. SystemRoutingController will never be released
- return false;
}
}
@@ -1442,8 +1472,7 @@ public final class MediaRouter2 {
if (!(obj instanceof TransferCallbackRecord)) {
return false;
}
- return mTransferCallback
- == ((TransferCallbackRecord) obj).mTransferCallback;
+ return mTransferCallback == ((TransferCallbackRecord) obj).mTransferCallback;
}
@Override
@@ -1481,11 +1510,17 @@ public final class MediaRouter2 {
static final class ControllerCreationRequest {
public final int mRequestId;
+ public final long mManagerRequestId;
public final MediaRoute2Info mRoute;
+ public final RoutingController mOldController;
- ControllerCreationRequest(int requestId, @NonNull MediaRoute2Info route) {
+ ControllerCreationRequest(int requestId, long managerRequestId,
+ @NonNull MediaRoute2Info route, @NonNull RoutingController oldController) {
mRequestId = requestId;
- mRoute = route;
+ mManagerRequestId = managerRequestId;
+ mRoute = Objects.requireNonNull(route, "route must not be null");
+ mOldController = Objects.requireNonNull(oldController,
+ "oldController must not be null");
}
}
@@ -1534,11 +1569,11 @@ public final class MediaRouter2 {
}
@Override
- public void getSessionHintsForCreatingSession(long uniqueRequestId,
- @NonNull MediaRoute2Info route) {
+ public void requestCreateSessionByManager(long managerRequestId,
+ RoutingSessionInfo oldSession, MediaRoute2Info route) {
mHandler.sendMessage(obtainMessage(
- MediaRouter2::onGetControllerHintsForCreatingSessionOnHandler,
- MediaRouter2.this, uniqueRequestId, route));
+ MediaRouter2::onRequestCreateControllerByManagerOnHandler,
+ MediaRouter2.this, oldSession, route, managerRequestId));
}
}
}
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index dad7859db622..4b09a5f19fb0 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -54,6 +54,12 @@ import java.util.stream.Collectors;
public final class MediaRouter2Manager {
private static final String TAG = "MR2Manager";
private static final Object sLock = new Object();
+ /**
+ * The request ID for requests not asked by this instance.
+ * Shouldn't be used for a valid request.
+ * @hide
+ */
+ public static final int REQUEST_ID_NONE = 0;
/** @hide */
@VisibleForTesting
public static final int TRANSFER_TIMEOUT_MS = 30_000;
@@ -480,7 +486,6 @@ public final class MediaRouter2Manager {
notifyTransferFailed(matchingRequest.mOldSessionInfo, requestedRoute);
return;
}
- releaseSession(matchingRequest.mOldSessionInfo);
notifyTransferred(matchingRequest.mOldSessionInfo, sessionInfo);
}
@@ -777,7 +782,7 @@ public final class MediaRouter2Manager {
if (client != null) {
try {
mMediaRouterService.requestCreateSessionWithManager(
- client, requestId, oldSession.getClientPackageName(), route);
+ client, requestId, oldSession, route);
} catch (RemoteException ex) {
Log.e(TAG, "requestCreateSession: Failed to send a request", ex);
}
diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java
index edf1fc58ecf5..a5d25e0771fd 100644
--- a/media/java/android/media/RoutingSessionInfo.java
+++ b/media/java/android/media/RoutingSessionInfo.java
@@ -220,7 +220,7 @@ public final class RoutingSessionInfo implements Parcelable {
}
/**
- * Gets information about how volume is handled on the session.
+ * Gets the information about how volume is handled on the session.
*
* @return {@link MediaRoute2Info#PLAYBACK_VOLUME_FIXED} or
* {@link MediaRoute2Info#PLAYBACK_VOLUME_VARIABLE}.
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index e8f18a59049e..515d610109ab 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -335,7 +335,7 @@ jobject MediaEvent::getLinearBlock() {
if (mLinearBlockObj != NULL) {
return mLinearBlockObj;
}
- mIonHandle = new C2HandleIon(mAvHandle->data[0], mDataLength);
+ mIonHandle = new C2HandleIon(dup(mAvHandle->data[0]), mDataLength);
std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(mIonHandle);
JNIEnv *env = AndroidRuntime::getJNIEnv();
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index 0979627e5e8d..ddefe266d897 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -126,6 +126,7 @@ public class MediaRouter2ManagerTest {
StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
if (instance != null) {
instance.setProxy(null);
+ instance.setSpy(null);
}
}
@@ -425,6 +426,79 @@ public class MediaRouter2ManagerTest {
@Test
@LargeTest
+ public void testTransferTwice() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
+ addRouterCallback(new RouteCallback() { });
+
+ CountDownLatch successLatch1 = new CountDownLatch(1);
+ CountDownLatch successLatch2 = new CountDownLatch(1);
+ CountDownLatch failureLatch = new CountDownLatch(1);
+ CountDownLatch managerOnSessionReleasedLatch = new CountDownLatch(1);
+ CountDownLatch serviceOnReleaseSessionLatch = new CountDownLatch(1);
+ List<RoutingSessionInfo> sessions = new ArrayList<>();
+
+ StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
+ assertNotNull(instance);
+ instance.setSpy(new StubMediaRoute2ProviderService.Spy() {
+ @Override
+ public void onReleaseSession(long requestId, String sessionId) {
+ serviceOnReleaseSessionLatch.countDown();
+ }
+ });
+
+ addManagerCallback(new MediaRouter2Manager.Callback() {
+ @Override
+ public void onTransferred(RoutingSessionInfo oldSession,
+ RoutingSessionInfo newSession) {
+ sessions.add(newSession);
+ if (successLatch1.getCount() > 0) {
+ successLatch1.countDown();
+ } else {
+ successLatch2.countDown();
+ }
+ }
+
+ @Override
+ public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) {
+ failureLatch.countDown();
+ }
+
+ @Override
+ public void onSessionReleased(RoutingSessionInfo session) {
+ managerOnSessionReleasedLatch.countDown();
+ }
+ });
+
+ MediaRoute2Info route1 = routes.get(ROUTE_ID1);
+ MediaRoute2Info route2 = routes.get(ROUTE_ID2);
+ assertNotNull(route1);
+ assertNotNull(route2);
+
+ mManager.selectRoute(mPackageName, route1);
+ assertTrue(successLatch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ mManager.selectRoute(mPackageName, route2);
+ assertTrue(successLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ // onTransferFailed/onSessionReleased should not be called.
+ assertFalse(failureLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertFalse(managerOnSessionReleasedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+
+ assertEquals(2, sessions.size());
+ List<String> activeSessionIds = mManager.getActiveSessions().stream()
+ .map(RoutingSessionInfo::getId)
+ .collect(Collectors.toList());
+ // The old session shouldn't appear on the active session list.
+ assertFalse(activeSessionIds.contains(sessions.get(0).getId()));
+ assertTrue(activeSessionIds.contains(sessions.get(1).getId()));
+
+ assertFalse(serviceOnReleaseSessionLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ mManager.releaseSession(sessions.get(0));
+ assertTrue(serviceOnReleaseSessionLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertFalse(managerOnSessionReleasedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ @LargeTest
public void testTransfer_ignored_fails() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
addRouterCallback(new RouteCallback() {});
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java
index 4551876d774a..a51e3714b6f7 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java
@@ -79,6 +79,7 @@ public class StubMediaRoute2ProviderService extends MediaRoute2ProviderService {
@GuardedBy("sLock")
private static StubMediaRoute2ProviderService sInstance;
private Proxy mProxy;
+ private Spy mSpy;
private void initializeRoutes() {
MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
@@ -256,6 +257,11 @@ public class StubMediaRoute2ProviderService extends MediaRoute2ProviderService {
@Override
public void onReleaseSession(long requestId, String sessionId) {
+ Spy spy = mSpy;
+ if (spy != null) {
+ spy.onReleaseSession(requestId, sessionId);
+ }
+
RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
if (sessionInfo == null) {
return;
@@ -375,7 +381,21 @@ public class StubMediaRoute2ProviderService extends MediaRoute2ProviderService {
mProxy = proxy;
}
+ public void setSpy(@Nullable Spy spy) {
+ mSpy = spy;
+ }
+
+ /**
+ * It overrides the original service
+ */
public static class Proxy {
public void onSetRouteVolume(String routeId, int volume, long requestId) {}
}
+
+ /**
+ * It gets notified but doesn't prevent the original methods to be called.
+ */
+ public static class Spy {
+ public void onReleaseSession(long requestId, String sessionId) {}
+ }
}
diff --git a/packages/OsuLogin/res/values-af/strings.xml b/packages/OsuLogin/res/values-af/strings.xml
deleted file mode 100644
index bfeee10622ae..000000000000
--- a/packages/OsuLogin/res/values-af/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Sluit aanlyn aan"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Kon nie aanmeld nie"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-am/strings.xml b/packages/OsuLogin/res/values-am/strings.xml
deleted file mode 100644
index e27c578343ef..000000000000
--- a/packages/OsuLogin/res/values-am/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"የመስመር ላይ ምዝገባ"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ምዝገባ አልተሳካም"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ar/strings.xml b/packages/OsuLogin/res/values-ar/strings.xml
deleted file mode 100644
index b72d7c1b45f8..000000000000
--- a/packages/OsuLogin/res/values-ar/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"الاشتراك على الإنترنت"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"تعذّر الاشتراك."</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-as/strings.xml b/packages/OsuLogin/res/values-as/strings.xml
deleted file mode 100644
index 422de3222871..000000000000
--- a/packages/OsuLogin/res/values-as/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"অনলাইনত ছাই আপ কৰক"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ছাইন আপ কৰিব পৰা নগ’ল"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-az/strings.xml b/packages/OsuLogin/res/values-az/strings.xml
deleted file mode 100644
index 977f93982619..000000000000
--- a/packages/OsuLogin/res/values-az/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Onlayn Qeydiyyat"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Qeydiyyat alınmadı"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-b+sr+Latn/strings.xml b/packages/OsuLogin/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index 6eb2cc119ef9..000000000000
--- a/packages/OsuLogin/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Onlajn registracija"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspela"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-be/strings.xml b/packages/OsuLogin/res/values-be/strings.xml
deleted file mode 100644
index 158c3f22ce21..000000000000
--- a/packages/OsuLogin/res/values-be/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Зарэгістравацца ў інтэрнэце"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Не ўдалося зарэгістравацца"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-bg/strings.xml b/packages/OsuLogin/res/values-bg/strings.xml
deleted file mode 100644
index ea3145dcb87f..000000000000
--- a/packages/OsuLogin/res/values-bg/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Онлайн регистрация"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Регистрацията не бе успешна"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-bn/strings.xml b/packages/OsuLogin/res/values-bn/strings.xml
deleted file mode 100644
index c9f615e2d017..000000000000
--- a/packages/OsuLogin/res/values-bn/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"অনলাইনে সাইন-আপ করুন"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"সাইন-আপ করা যায়নি"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-bs/strings.xml b/packages/OsuLogin/res/values-bs/strings.xml
deleted file mode 100644
index e9b9751c95cf..000000000000
--- a/packages/OsuLogin/res/values-bs/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online registracija"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspjela"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ca/strings.xml b/packages/OsuLogin/res/values-ca/strings.xml
deleted file mode 100644
index 7d9309616592..000000000000
--- a/packages/OsuLogin/res/values-ca/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Registre en línia"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Ha fallat el registre"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-cs/strings.xml b/packages/OsuLogin/res/values-cs/strings.xml
deleted file mode 100644
index b9cb7942bc79..000000000000
--- a/packages/OsuLogin/res/values-cs/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online registrace"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registrace selhala"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-da/strings.xml b/packages/OsuLogin/res/values-da/strings.xml
deleted file mode 100644
index 68c93b78a46d..000000000000
--- a/packages/OsuLogin/res/values-da/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online registrering"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registrering mislykkedes"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-de/strings.xml b/packages/OsuLogin/res/values-de/strings.xml
deleted file mode 100644
index 7e5a3106db4a..000000000000
--- a/packages/OsuLogin/res/values-de/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online-Registrierung"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registrierung fehlgeschlagen"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-el/strings.xml b/packages/OsuLogin/res/values-el/strings.xml
deleted file mode 100644
index a58e4817a3cb..000000000000
--- a/packages/OsuLogin/res/values-el/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Εγγραφή στο διαδίκτυο"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Αποτυχία εγγραφής"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-en-rAU/strings.xml b/packages/OsuLogin/res/values-en-rAU/strings.xml
deleted file mode 100644
index fbbcab17c412..000000000000
--- a/packages/OsuLogin/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-en-rCA/strings.xml b/packages/OsuLogin/res/values-en-rCA/strings.xml
deleted file mode 100644
index fbbcab17c412..000000000000
--- a/packages/OsuLogin/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-en-rGB/strings.xml b/packages/OsuLogin/res/values-en-rGB/strings.xml
deleted file mode 100644
index fbbcab17c412..000000000000
--- a/packages/OsuLogin/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-en-rIN/strings.xml b/packages/OsuLogin/res/values-en-rIN/strings.xml
deleted file mode 100644
index fbbcab17c412..000000000000
--- a/packages/OsuLogin/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-en-rXC/strings.xml b/packages/OsuLogin/res/values-en-rXC/strings.xml
deleted file mode 100644
index af7ff67c86b2..000000000000
--- a/packages/OsuLogin/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎OsuLogin‎‏‎‎‏‎"</string>
- <string name="action_bar_label" msgid="550995560341508693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎Online Sign Up‎‏‎‎‏‎"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎Sign-up failed‎‏‎‎‏‎"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-es-rUS/strings.xml b/packages/OsuLogin/res/values-es-rUS/strings.xml
deleted file mode 100644
index 144804cd891c..000000000000
--- a/packages/OsuLogin/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Registrarse en línea"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Se produjo un error de registro"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-es/strings.xml b/packages/OsuLogin/res/values-es/strings.xml
deleted file mode 100644
index 3ad95cd8cdc9..000000000000
--- a/packages/OsuLogin/res/values-es/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Registro online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Error al completar el registro"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-et/strings.xml b/packages/OsuLogin/res/values-et/strings.xml
deleted file mode 100644
index 94c5cea646a5..000000000000
--- a/packages/OsuLogin/res/values-et/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Veebis registreerimine"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registreerimine ebaõnnestus"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-eu/strings.xml b/packages/OsuLogin/res/values-eu/strings.xml
deleted file mode 100644
index 30caa8740a1d..000000000000
--- a/packages/OsuLogin/res/values-eu/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Sarean izen-ematea"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Ezin izan da eman izena"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-fa/strings.xml b/packages/OsuLogin/res/values-fa/strings.xml
deleted file mode 100644
index 300520336037..000000000000
--- a/packages/OsuLogin/res/values-fa/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ثبت‌نام آنلاین"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ثبت‌نام انجام نشد"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-fi/strings.xml b/packages/OsuLogin/res/values-fi/strings.xml
deleted file mode 100644
index 24eac8acc8d3..000000000000
--- a/packages/OsuLogin/res/values-fi/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Rekisteröidy verkossa"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Rekisteröityminen ei onnistunut"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-fr-rCA/strings.xml b/packages/OsuLogin/res/values-fr-rCA/strings.xml
deleted file mode 100644
index bcaa6621e803..000000000000
--- a/packages/OsuLogin/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Inscription en ligne"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Échec de l\'inscription"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-fr/strings.xml b/packages/OsuLogin/res/values-fr/strings.xml
deleted file mode 100644
index bcaa6621e803..000000000000
--- a/packages/OsuLogin/res/values-fr/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Inscription en ligne"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Échec de l\'inscription"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-gl/strings.xml b/packages/OsuLogin/res/values-gl/strings.xml
deleted file mode 100644
index 5fc44440d01d..000000000000
--- a/packages/OsuLogin/res/values-gl/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Rexistro en liña"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Produciuse un erro co rexistro"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-gu/strings.xml b/packages/OsuLogin/res/values-gu/strings.xml
deleted file mode 100644
index 8449963b1705..000000000000
--- a/packages/OsuLogin/res/values-gu/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ઑનલાઇન સાઇન અપ કરો"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"સાઇન અપ નિષ્ફળ"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-hi/strings.xml b/packages/OsuLogin/res/values-hi/strings.xml
deleted file mode 100644
index 9e07438047f0..000000000000
--- a/packages/OsuLogin/res/values-hi/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ऑनलाइन साइन अप करें"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"साइन अप नहीं किया जा सका"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-hr/strings.xml b/packages/OsuLogin/res/values-hr/strings.xml
deleted file mode 100644
index e9b9751c95cf..000000000000
--- a/packages/OsuLogin/res/values-hr/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online registracija"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspjela"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-hu/strings.xml b/packages/OsuLogin/res/values-hu/strings.xml
deleted file mode 100644
index cb0e036fbbd3..000000000000
--- a/packages/OsuLogin/res/values-hu/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online regisztráció"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"A regisztráció nem sikerült"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-hy/strings.xml b/packages/OsuLogin/res/values-hy/strings.xml
deleted file mode 100644
index ae1c36a0b341..000000000000
--- a/packages/OsuLogin/res/values-hy/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Առցանց գրանցում"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Չհաջողվեց գրանցվել"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-in/strings.xml b/packages/OsuLogin/res/values-in/strings.xml
deleted file mode 100644
index 6aaf6942c25a..000000000000
--- a/packages/OsuLogin/res/values-in/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Pendaftaran Online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Pendaftaran gagal"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-is/strings.xml b/packages/OsuLogin/res/values-is/strings.xml
deleted file mode 100644
index f1ae520a63ee..000000000000
--- a/packages/OsuLogin/res/values-is/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Skráning á netinu"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Skráning mistókst"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-it/strings.xml b/packages/OsuLogin/res/values-it/strings.xml
deleted file mode 100644
index fbff7b0f4c75..000000000000
--- a/packages/OsuLogin/res/values-it/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Registrazione online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registrazione non riuscita"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-iw/strings.xml b/packages/OsuLogin/res/values-iw/strings.xml
deleted file mode 100644
index 866ef880759c..000000000000
--- a/packages/OsuLogin/res/values-iw/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"הרשמה אונליין"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ההרשמה נכשלה"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ja/strings.xml b/packages/OsuLogin/res/values-ja/strings.xml
deleted file mode 100644
index 8a220d605afb..000000000000
--- a/packages/OsuLogin/res/values-ja/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"オンライン登録"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"登録できませんでした"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ka/strings.xml b/packages/OsuLogin/res/values-ka/strings.xml
deleted file mode 100644
index bf08006c47b3..000000000000
--- a/packages/OsuLogin/res/values-ka/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ონლაინ რეგისტრაცია"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"რეგისტრაცია ვერ მოხერხდა"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-kk/strings.xml b/packages/OsuLogin/res/values-kk/strings.xml
deleted file mode 100644
index 8b87356ad547..000000000000
--- a/packages/OsuLogin/res/values-kk/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Онлайн тіркелу"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Тіркелмеді."</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-km/strings.xml b/packages/OsuLogin/res/values-km/strings.xml
deleted file mode 100644
index f58ccc330c5f..000000000000
--- a/packages/OsuLogin/res/values-km/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ការចុះឈ្មោះ​លើអ៊ីនធឺណិត"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ការចុះឈ្មោះ​មិនបានសម្រេច"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-kn/strings.xml b/packages/OsuLogin/res/values-kn/strings.xml
deleted file mode 100644
index 49a65627487e..000000000000
--- a/packages/OsuLogin/res/values-kn/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ಆನ್‌ಲೈನ್ ಸೈನ್ ಅಪ್"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ಸೈನ್ ಅಪ್ ವಿಫಲವಾಗಿದೆ"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ko/strings.xml b/packages/OsuLogin/res/values-ko/strings.xml
deleted file mode 100644
index e647ca05f97a..000000000000
--- a/packages/OsuLogin/res/values-ko/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"온라인 가입"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"가입에 실패했습니다."</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ky/strings.xml b/packages/OsuLogin/res/values-ky/strings.xml
deleted file mode 100644
index 42da248ac9e5..000000000000
--- a/packages/OsuLogin/res/values-ky/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Интернет аркылуу катталуу"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Катталган жоксуз"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-lo/strings.xml b/packages/OsuLogin/res/values-lo/strings.xml
deleted file mode 100644
index 9ff224170908..000000000000
--- a/packages/OsuLogin/res/values-lo/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ສະໝັກອອນລາຍ"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ສະໝັກບໍ່ສຳເລັດ"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-lt/strings.xml b/packages/OsuLogin/res/values-lt/strings.xml
deleted file mode 100644
index 1a4c06e87955..000000000000
--- a/packages/OsuLogin/res/values-lt/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Internetinis prisiregistravimas"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Nepavyko prisiregistruoti"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-lv/strings.xml b/packages/OsuLogin/res/values-lv/strings.xml
deleted file mode 100644
index 11cdb974440f..000000000000
--- a/packages/OsuLogin/res/values-lv/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Reģistrācija tiešsaistē"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Reģistrācija neizdevās."</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-mk/strings.xml b/packages/OsuLogin/res/values-mk/strings.xml
deleted file mode 100644
index de608e12cab7..000000000000
--- a/packages/OsuLogin/res/values-mk/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Онлајн регистрација"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Регистрацијата не успеа"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ml/strings.xml b/packages/OsuLogin/res/values-ml/strings.xml
deleted file mode 100644
index 8e797c8e6e98..000000000000
--- a/packages/OsuLogin/res/values-ml/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ഓൺലെെൻ സെെൻ അപ്പ്"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"സൈൻ അപ്പ് ചെയ്യാനായില്ല"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-mn/strings.xml b/packages/OsuLogin/res/values-mn/strings.xml
deleted file mode 100644
index 59d79d0c0a5d..000000000000
--- a/packages/OsuLogin/res/values-mn/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Онлайнаар бүртгүүлэх"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Бүртгүүлж чадсангүй"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-mr/strings.xml b/packages/OsuLogin/res/values-mr/strings.xml
deleted file mode 100644
index 15479a6e2735..000000000000
--- a/packages/OsuLogin/res/values-mr/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ऑनलाइन साइन अप करा"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"साइन-अप करता आले नाही"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ms/strings.xml b/packages/OsuLogin/res/values-ms/strings.xml
deleted file mode 100644
index 7e1cf9535319..000000000000
--- a/packages/OsuLogin/res/values-ms/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Pendaftaran Dalam Talian"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Pendaftaran gagal"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-my/strings.xml b/packages/OsuLogin/res/values-my/strings.xml
deleted file mode 100644
index 1bd992e8485b..000000000000
--- a/packages/OsuLogin/res/values-my/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"အွန်လိုင်း အကောင့်ဖွင့်ရန်"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"အကောင့်ဖွင့်၍ မရပါ"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-nb/strings.xml b/packages/OsuLogin/res/values-nb/strings.xml
deleted file mode 100644
index 2e0c47a18fca..000000000000
--- a/packages/OsuLogin/res/values-nb/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Registrering på nettet"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registreringen mislyktes"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ne/strings.xml b/packages/OsuLogin/res/values-ne/strings.xml
deleted file mode 100644
index 16bd92f57e23..000000000000
--- a/packages/OsuLogin/res/values-ne/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"अनलाइन साइन अप"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"साइन अप गर्न सकिएन"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-nl/strings.xml b/packages/OsuLogin/res/values-nl/strings.xml
deleted file mode 100644
index 7cf8bd2da1ac..000000000000
--- a/packages/OsuLogin/res/values-nl/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online aanmelding"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Aanmelding mislukt"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-or/strings.xml b/packages/OsuLogin/res/values-or/strings.xml
deleted file mode 100644
index e0584d716d66..000000000000
--- a/packages/OsuLogin/res/values-or/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ଅନଲାଇନ୍ ସାଇନ୍ ଅପ୍ କରନ୍ତୁ"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ସାଇନ୍ ଅପ୍ ବିଫଳ ହୋଇଛି"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-pa/strings.xml b/packages/OsuLogin/res/values-pa/strings.xml
deleted file mode 100644
index 7e47d0e0960e..000000000000
--- a/packages/OsuLogin/res/values-pa/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ਆਨਲਾਈਨ ਸਾਈਨ-ਅੱਪ ਕਰੋ"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ਸਾਈਨ-ਅੱਪ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-pl/strings.xml b/packages/OsuLogin/res/values-pl/strings.xml
deleted file mode 100644
index c0722ab6aaf6..000000000000
--- a/packages/OsuLogin/res/values-pl/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Rejestracja online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Nie udało się zarejestrować"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-pt-rBR/strings.xml b/packages/OsuLogin/res/values-pt-rBR/strings.xml
deleted file mode 100644
index c9fe3772504d..000000000000
--- a/packages/OsuLogin/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Inscrição on-line"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-pt-rPT/strings.xml b/packages/OsuLogin/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 0059281416c8..000000000000
--- a/packages/OsuLogin/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Inscrição online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição."</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-pt/strings.xml b/packages/OsuLogin/res/values-pt/strings.xml
deleted file mode 100644
index c9fe3772504d..000000000000
--- a/packages/OsuLogin/res/values-pt/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Inscrição on-line"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ro/strings.xml b/packages/OsuLogin/res/values-ro/strings.xml
deleted file mode 100644
index eead127dd877..000000000000
--- a/packages/OsuLogin/res/values-ro/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Înscriere online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Nu s-a înscris"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ru/strings.xml b/packages/OsuLogin/res/values-ru/strings.xml
deleted file mode 100644
index a271ef7c00fc..000000000000
--- a/packages/OsuLogin/res/values-ru/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Регистрация в Интернете"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Не удалось зарегистрироваться."</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-si/strings.xml b/packages/OsuLogin/res/values-si/strings.xml
deleted file mode 100644
index 52e5979e7078..000000000000
--- a/packages/OsuLogin/res/values-si/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"සබැඳි ලියාපදිංචිය"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ලියාපදිංචිය අසාර්ථක විය"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-sk/strings.xml b/packages/OsuLogin/res/values-sk/strings.xml
deleted file mode 100644
index f6b9f702d3b7..000000000000
--- a/packages/OsuLogin/res/values-sk/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online registrácia"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registrácia zlyhala"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-sl/strings.xml b/packages/OsuLogin/res/values-sl/strings.xml
deleted file mode 100644
index 6e6b95ce07f1..000000000000
--- a/packages/OsuLogin/res/values-sl/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Spletna registracija"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registracija ni uspela"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-sq/strings.xml b/packages/OsuLogin/res/values-sq/strings.xml
deleted file mode 100644
index f67a2382bdac..000000000000
--- a/packages/OsuLogin/res/values-sq/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Regjistrimi në linjë"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Regjistrimi dështoi"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-sr/strings.xml b/packages/OsuLogin/res/values-sr/strings.xml
deleted file mode 100644
index 14e0828d5b83..000000000000
--- a/packages/OsuLogin/res/values-sr/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Онлајн регистрација"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Регистрација није успела"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-sv/strings.xml b/packages/OsuLogin/res/values-sv/strings.xml
deleted file mode 100644
index ea5fdfda7004..000000000000
--- a/packages/OsuLogin/res/values-sv/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Registrering online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registreringen misslyckades"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-sw/strings.xml b/packages/OsuLogin/res/values-sw/strings.xml
deleted file mode 100644
index c20a4023dda5..000000000000
--- a/packages/OsuLogin/res/values-sw/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Kujisajili Mtandaoni"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Imeshindwa kukusajili"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ta/strings.xml b/packages/OsuLogin/res/values-ta/strings.xml
deleted file mode 100644
index e2eb567ef92e..000000000000
--- a/packages/OsuLogin/res/values-ta/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ஆன்லைனில் பதிவு செய்"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"பதிவு செய்ய முடியவில்லை"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-te/strings.xml b/packages/OsuLogin/res/values-te/strings.xml
deleted file mode 100644
index 56b0b44d4802..000000000000
--- a/packages/OsuLogin/res/values-te/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"ఆన్‌లైన్ సైన్ అప్"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"సైన్-అప్ విఫలమయ్యింది"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-th/strings.xml b/packages/OsuLogin/res/values-th/strings.xml
deleted file mode 100644
index 552dca2c15e3..000000000000
--- a/packages/OsuLogin/res/values-th/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"การลงชื่อสมัครใช้ออนไลน์"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"ลงชื่อสมัครใช้ไม่สำเร็จ"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-tl/strings.xml b/packages/OsuLogin/res/values-tl/strings.xml
deleted file mode 100644
index ba89e9654213..000000000000
--- a/packages/OsuLogin/res/values-tl/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Pag-sign Up Online"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Hindi nakapag-sign up"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-tr/strings.xml b/packages/OsuLogin/res/values-tr/strings.xml
deleted file mode 100644
index 1d927fef4d16..000000000000
--- a/packages/OsuLogin/res/values-tr/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Online Kaydolma"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Kaydolma işlemi başarısız oldu"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-uk/strings.xml b/packages/OsuLogin/res/values-uk/strings.xml
deleted file mode 100644
index 6e60ff008c0f..000000000000
--- a/packages/OsuLogin/res/values-uk/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Онлайн-реєстрація"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Не вдалося зареєструватись"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-ur/strings.xml b/packages/OsuLogin/res/values-ur/strings.xml
deleted file mode 100644
index eed7686c4fe9..000000000000
--- a/packages/OsuLogin/res/values-ur/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"آن لائن سائن اپ کریں"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"سائن اپ ناکام ہو گیا"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-uz/strings.xml b/packages/OsuLogin/res/values-uz/strings.xml
deleted file mode 100644
index 152d129fe05a..000000000000
--- a/packages/OsuLogin/res/values-uz/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Onlayn registratsiya"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Registratsiya qilinmadi"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-vi/strings.xml b/packages/OsuLogin/res/values-vi/strings.xml
deleted file mode 100644
index 845580760965..000000000000
--- a/packages/OsuLogin/res/values-vi/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Đăng ký trực tuyến"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Không đăng ký được"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-zh-rCN/strings.xml b/packages/OsuLogin/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 7f13647bfccd..000000000000
--- a/packages/OsuLogin/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"在线注册"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"注册失败"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-zh-rHK/strings.xml b/packages/OsuLogin/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 873179189b24..000000000000
--- a/packages/OsuLogin/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"網上申請"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"無法申請"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-zh-rTW/strings.xml b/packages/OsuLogin/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 79208c8d7387..000000000000
--- a/packages/OsuLogin/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"線上註冊"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"註冊失敗"</string>
-</resources>
diff --git a/packages/OsuLogin/res/values-zu/strings.xml b/packages/OsuLogin/res/values-zu/strings.xml
deleted file mode 100644
index 27ac6bb755f9..000000000000
--- a/packages/OsuLogin/res/values-zu/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="8288271429327488421">"I-OsuLogin"</string>
- <string name="action_bar_label" msgid="550995560341508693">"Ukubhalisa Okuku-inthanethi"</string>
- <string name="sign_up_failed" msgid="837216244603867568">"Ukubhalisa kuhlulekile"</string>
-</resources>
diff --git a/packages/SettingsLib/AdaptiveIcon/res/values-night/colors.xml b/packages/SettingsLib/AdaptiveIcon/res/values-night/colors.xml
new file mode 100644
index 000000000000..f985c1e2bd42
--- /dev/null
+++ b/packages/SettingsLib/AdaptiveIcon/res/values-night/colors.xml
@@ -0,0 +1,19 @@
+<?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>
+ <color name="advanced_outline_color">#FFFFFFFF</color> <!-- icon outline color -->
+</resources>
diff --git a/packages/SoundPicker/res/values-af/strings.xml b/packages/SoundPicker/res/values-af/strings.xml
index 3c0efe9704bb..fd857b1c3cc4 100644
--- a/packages/SoundPicker/res/values-af/strings.xml
+++ b/packages/SoundPicker/res/values-af/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Vee uit"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Kan nie gepasmaakte luitoon byvoeg nie"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Kan nie gepasmaakte luitoon uitvee nie"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Klanke"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-b+sr+Latn/strings.xml b/packages/SoundPicker/res/values-b+sr+Latn/strings.xml
index eb53de69f27a..947c85c8ad91 100644
--- a/packages/SoundPicker/res/values-b+sr+Latn/strings.xml
+++ b/packages/SoundPicker/res/values-b+sr+Latn/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Izbriši"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Dodavanje prilagođene melodije zvona nije uspelo"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Brisanje prilagođene melodije zvona nije uspelo"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Zvukovi"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-bg/strings.xml b/packages/SoundPicker/res/values-bg/strings.xml
index 4bc8228a85fc..4277d2851e8c 100644
--- a/packages/SoundPicker/res/values-bg/strings.xml
+++ b/packages/SoundPicker/res/values-bg/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Изтриване"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Персонализираната мелодия не може да се добави"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Персонализираната мелодия не може да се изтрие"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-bs/strings.xml b/packages/SoundPicker/res/values-bs/strings.xml
index 893d832919f4..0c8d33f4187e 100644
--- a/packages/SoundPicker/res/values-bs/strings.xml
+++ b/packages/SoundPicker/res/values-bs/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Izbriši"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nije moguće dodati prilagođenu melodiju zvona"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nije moguće izbrisati prilagođenu melodiju zvona"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Zvukovi"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-ca/strings.xml b/packages/SoundPicker/res/values-ca/strings.xml
index d14c87112546..ed96f70c7c01 100644
--- a/packages/SoundPicker/res/values-ca/strings.xml
+++ b/packages/SoundPicker/res/values-ca/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Suprimeix"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"No es pot afegir el so de trucada personalitzat"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"No es pot suprimir el so de trucada personalitzat"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sons"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-cs/strings.xml b/packages/SoundPicker/res/values-cs/strings.xml
index 7e3accf11f62..e8fc97e44174 100644
--- a/packages/SoundPicker/res/values-cs/strings.xml
+++ b/packages/SoundPicker/res/values-cs/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Smazat"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Vlastní vyzváněcí tón se nepodařilo přidat"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Vlastní vyzváněcí tón se nepodařilo smazat"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Zvuky"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-da/strings.xml b/packages/SoundPicker/res/values-da/strings.xml
index bccd4223c741..b4437dc805ac 100644
--- a/packages/SoundPicker/res/values-da/strings.xml
+++ b/packages/SoundPicker/res/values-da/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Slet"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Den tilpassede ringetone kunne ikke tilføjes"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Den tilpassede ringetone kunne ikke slettes"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Lyde"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-el/strings.xml b/packages/SoundPicker/res/values-el/strings.xml
index d0d9d0d495a2..41e9b0ccf334 100644
--- a/packages/SoundPicker/res/values-el/strings.xml
+++ b/packages/SoundPicker/res/values-el/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Διαγραφή"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Δεν είναι δυνατή η προσθήκη προσαρμοσμένου ήχου κλήσης"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Δεν είναι δυνατή η διαγραφή προσαρμοσμένου ήχου κλήσης"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Ήχοι"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-es-rUS/strings.xml b/packages/SoundPicker/res/values-es-rUS/strings.xml
index 42b61c113fff..5bf73b2fe2b8 100644
--- a/packages/SoundPicker/res/values-es-rUS/strings.xml
+++ b/packages/SoundPicker/res/values-es-rUS/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Borrar"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"No se puede agregar el tono personalizado"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"No se puede borrar el tono personalizado"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sonidos"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-es/strings.xml b/packages/SoundPicker/res/values-es/strings.xml
index e9e73ba4ce65..a77f656f14e5 100644
--- a/packages/SoundPicker/res/values-es/strings.xml
+++ b/packages/SoundPicker/res/values-es/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Eliminar"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"No se ha podido añadir un tono de llamada personalizado"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"No se ha podido eliminar un tono de llamada personalizado"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sonidos"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-et/strings.xml b/packages/SoundPicker/res/values-et/strings.xml
index 988476375c38..fa680accddf5 100644
--- a/packages/SoundPicker/res/values-et/strings.xml
+++ b/packages/SoundPicker/res/values-et/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Kustuta"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Kohandatud helinat ei õnnestu lisada"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Kohandatud helinat ei õnnestu kustutada"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Helid"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-fa/strings.xml b/packages/SoundPicker/res/values-fa/strings.xml
index 4e55cbbcb632..dc7c214977f2 100644
--- a/packages/SoundPicker/res/values-fa/strings.xml
+++ b/packages/SoundPicker/res/values-fa/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"حذف"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"افزودن آهنگ زنگ سفارشی ممکن نیست"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"حذف آهنگ زنگ سفارشی ممکن نیست"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"صداها"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-fi/strings.xml b/packages/SoundPicker/res/values-fi/strings.xml
index 86690bb04d6e..9f64f8379b43 100644
--- a/packages/SoundPicker/res/values-fi/strings.xml
+++ b/packages/SoundPicker/res/values-fi/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Poista"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Muokatun soittoäänen lisääminen epäonnistui."</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Muokatun soittoäänen poistaminen epäonnistui."</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Äänet"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-gl/strings.xml b/packages/SoundPicker/res/values-gl/strings.xml
index ac7283934084..59a9d066a7aa 100644
--- a/packages/SoundPicker/res/values-gl/strings.xml
+++ b/packages/SoundPicker/res/values-gl/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Eliminar"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Non se pode engadir un ton de chamada personalizado"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Non se pode eliminar un ton de chamada personalizado"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sons"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-hr/strings.xml b/packages/SoundPicker/res/values-hr/strings.xml
index bcb36d0393f5..f74c4ae69e80 100644
--- a/packages/SoundPicker/res/values-hr/strings.xml
+++ b/packages/SoundPicker/res/values-hr/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Izbriši"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Dodavanje prilagođene melodije zvona nije moguće"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Brisanje prilagođene melodije zvona nije moguće"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Zvukovi"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-is/strings.xml b/packages/SoundPicker/res/values-is/strings.xml
index 3971e7030c46..d0fce78ff9d9 100644
--- a/packages/SoundPicker/res/values-is/strings.xml
+++ b/packages/SoundPicker/res/values-is/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Eyða"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Get ekki bætt sérsniðnum hringitóni við"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Get ekki eytt sérsniðnum hringitóni"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Hljóð"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-ja/strings.xml b/packages/SoundPicker/res/values-ja/strings.xml
index 43895c2c12c0..7c2aec60df75 100644
--- a/packages/SoundPicker/res/values-ja/strings.xml
+++ b/packages/SoundPicker/res/values-ja/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"削除"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"カスタム着信音を追加できません"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"カスタム着信音を削除できません"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"サウンド"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-ka/strings.xml b/packages/SoundPicker/res/values-ka/strings.xml
index 5be1d954650a..1cfe2401a99b 100644
--- a/packages/SoundPicker/res/values-ka/strings.xml
+++ b/packages/SoundPicker/res/values-ka/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"წაშლა"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"მორგებული ზარის დამატება შეუძლებელია"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"მორგებული ზარის წაშლა შეუძლებელია"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"ხმები"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-kn/strings.xml b/packages/SoundPicker/res/values-kn/strings.xml
index 7786039eb84f..e6a05c2b4e2d 100644
--- a/packages/SoundPicker/res/values-kn/strings.xml
+++ b/packages/SoundPicker/res/values-kn/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"ಅಳಿಸಿ"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"ಕಸ್ಟಮ್ ರಿಂಗ್‌ಟೋನ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"ಕಸ್ಟಮ್ ರಿಂಗ್‌ಟೋನ್ ಅಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"ಧ್ವನಿಗಳು"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-lo/strings.xml b/packages/SoundPicker/res/values-lo/strings.xml
index 8b9359e389f4..8bcae0df95d2 100644
--- a/packages/SoundPicker/res/values-lo/strings.xml
+++ b/packages/SoundPicker/res/values-lo/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"​ລຶບ"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Unable to add custom ringtone"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Unable to delete custom ringtone"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"ສຽງ"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-mk/strings.xml b/packages/SoundPicker/res/values-mk/strings.xml
index 00caeac0be41..545d5ed2f8f2 100644
--- a/packages/SoundPicker/res/values-mk/strings.xml
+++ b/packages/SoundPicker/res/values-mk/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Избриши"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Не може да се додаде приспособена мелодија"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Не може да се избрише приспособена мелодија"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Звуци"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-my/strings.xml b/packages/SoundPicker/res/values-my/strings.xml
index e6f80c994ac2..62163e950475 100644
--- a/packages/SoundPicker/res/values-my/strings.xml
+++ b/packages/SoundPicker/res/values-my/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"ဖျက်ရန်"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"စိတ်ကြိုက်ဖုန်းမြည်သံကို ထည့်သွင်း၍မရပါ"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"စိတ်ကြိုက်ဖုန်းမြည်သံကို ဖျက်၍မရပါ"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"အသံများ"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-nb/strings.xml b/packages/SoundPicker/res/values-nb/strings.xml
index d8d1f201a5ae..e4e259af541d 100644
--- a/packages/SoundPicker/res/values-nb/strings.xml
+++ b/packages/SoundPicker/res/values-nb/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Slett"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Kan ikke legge til egendefinert ringelyd"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Kan ikke slette egendefinert ringelyd"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Lyder"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-nl/strings.xml b/packages/SoundPicker/res/values-nl/strings.xml
index 3a68ac1a7287..5b6fb70b2a82 100644
--- a/packages/SoundPicker/res/values-nl/strings.xml
+++ b/packages/SoundPicker/res/values-nl/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Verwijderen"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Toevoegen van aangepaste ringtone is mislukt"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Verwijderen van aangepaste ringtone is mislukt"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Geluiden"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-pt-rBR/strings.xml b/packages/SoundPicker/res/values-pt-rBR/strings.xml
index ab1d5da03ba3..7b545e15ccaa 100644
--- a/packages/SoundPicker/res/values-pt-rBR/strings.xml
+++ b/packages/SoundPicker/res/values-pt-rBR/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Excluir"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Não foi possível adicionar o toque personalizado"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Não foi possível excluir o toque personalizado"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sons"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-pt-rPT/strings.xml b/packages/SoundPicker/res/values-pt-rPT/strings.xml
index efb768883bc6..5d742f1d75c7 100644
--- a/packages/SoundPicker/res/values-pt-rPT/strings.xml
+++ b/packages/SoundPicker/res/values-pt-rPT/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Eliminar"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Não foi possível adicionar o toque personalizado"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Não foi possível eliminar o toque personalizado"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sons"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-pt/strings.xml b/packages/SoundPicker/res/values-pt/strings.xml
index ab1d5da03ba3..7b545e15ccaa 100644
--- a/packages/SoundPicker/res/values-pt/strings.xml
+++ b/packages/SoundPicker/res/values-pt/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Excluir"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Não foi possível adicionar o toque personalizado"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Não foi possível excluir o toque personalizado"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sons"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-ro/strings.xml b/packages/SoundPicker/res/values-ro/strings.xml
index 337158e392c7..6190f7f8eac3 100644
--- a/packages/SoundPicker/res/values-ro/strings.xml
+++ b/packages/SoundPicker/res/values-ro/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Ștergeți"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nu se poate adăuga tonul de sonerie personalizat"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nu se poate șterge tonul de sonerie personalizat"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sunete"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-ru/strings.xml b/packages/SoundPicker/res/values-ru/strings.xml
index 058bb6f16d63..0d48ac1e8785 100644
--- a/packages/SoundPicker/res/values-ru/strings.xml
+++ b/packages/SoundPicker/res/values-ru/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Удалить"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Не удалось добавить рингтон"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Не удалось удалить рингтон"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Звуки"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-si/strings.xml b/packages/SoundPicker/res/values-si/strings.xml
index 5df39906a909..1872b6b27f30 100644
--- a/packages/SoundPicker/res/values-si/strings.xml
+++ b/packages/SoundPicker/res/values-si/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"මකන්න"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"අභිරුචි නාද රිද්මය එක් කළ නොහැකිය"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"අභිරුචි නාද රිද්මය මැකිය නොහැකිය"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"ශබ්ද"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-sl/strings.xml b/packages/SoundPicker/res/values-sl/strings.xml
index 024cbe895d99..77a2a2cef0e7 100644
--- a/packages/SoundPicker/res/values-sl/strings.xml
+++ b/packages/SoundPicker/res/values-sl/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Izbriši"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Tona zvonjenja po meri ni mogoče dodati"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Tona zvonjenja po meri ni mogoče izbrisati"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Zvoki"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-sq/strings.xml b/packages/SoundPicker/res/values-sq/strings.xml
index cf2667209866..e35dd71c3beb 100644
--- a/packages/SoundPicker/res/values-sq/strings.xml
+++ b/packages/SoundPicker/res/values-sq/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Fshi"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nuk mund të shtojë ton zileje të personalizuar"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nuk mund të fshijë ton zileje të personalizuar"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Tingujt"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-sr/strings.xml b/packages/SoundPicker/res/values-sr/strings.xml
index 4b37d614d2c6..bc573f5a2662 100644
--- a/packages/SoundPicker/res/values-sr/strings.xml
+++ b/packages/SoundPicker/res/values-sr/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Избриши"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Додавање прилагођене мелодије звона није успело"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Брисање прилагођене мелодије звона није успело"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Звукови"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-sw/strings.xml b/packages/SoundPicker/res/values-sw/strings.xml
index 14e8d75613ff..b0234500b64c 100644
--- a/packages/SoundPicker/res/values-sw/strings.xml
+++ b/packages/SoundPicker/res/values-sw/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Futa"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Imeshindwa kuongeza mlio maalum wa simu"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Imeshindwa kufuta mlio maalum wa simu"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sauti"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-tl/strings.xml b/packages/SoundPicker/res/values-tl/strings.xml
index 01c33b3758c1..c0c17128a53f 100644
--- a/packages/SoundPicker/res/values-tl/strings.xml
+++ b/packages/SoundPicker/res/values-tl/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"I-delete"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Hindi maidagdag ang custom na ringtone"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Hindi ma-delete ang custom na ringtone"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Mga Tunog"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-tr/strings.xml b/packages/SoundPicker/res/values-tr/strings.xml
index 266edbb4a8a7..955c23f068bf 100644
--- a/packages/SoundPicker/res/values-tr/strings.xml
+++ b/packages/SoundPicker/res/values-tr/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Sil"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Özel zil sesi eklenemiyor"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Özel zil sesi silinemiyor"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Sesler"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-zu/strings.xml b/packages/SoundPicker/res/values-zu/strings.xml
index c66da42fe0a1..29a8ffe846b2 100644
--- a/packages/SoundPicker/res/values-zu/strings.xml
+++ b/packages/SoundPicker/res/values-zu/strings.xml
@@ -25,6 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"Susa"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"Ayikwazi ukwengeza ithoni yokukhala yangokwezifiso"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Ayikwazi ukususa ithoni yokukhala yangokwezifiso"</string>
- <!-- no translation found for app_label (3091611356093417332) -->
- <skip />
+ <string name="app_label" msgid="3091611356093417332">"Imisindo"</string>
</resources>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
index bcff63471302..9d52098f37d5 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -30,7 +30,7 @@ import java.io.PrintWriter;
*/
@ProvidesInterface(version = FalsingManager.VERSION)
public interface FalsingManager {
- int VERSION = 3;
+ int VERSION = 4;
void onSuccessfulUnlock();
@@ -88,11 +88,11 @@ public interface FalsingManager {
void onScreenOff();
- void onNotificatonStopDismissing();
+ void onNotificationStopDismissing();
void onNotificationDismissed();
- void onNotificatonStartDismissing();
+ void onNotificationStartDismissing();
void onNotificationDoubleTap(boolean accepted, float dx, float dy);
diff --git a/packages/SystemUI/res-keyguard/drawable/qs_media_seamless_background.xml b/packages/SystemUI/res-keyguard/drawable/qs_media_seamless_background.xml
new file mode 100644
index 000000000000..3790378ff3ae
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/qs_media_seamless_background.xml
@@ -0,0 +1,26 @@
+<?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
+ -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/media_seamless_border">
+ <item android:id="@android:id/background">
+ <shape
+ android:color="@android:color/transparent">
+ <stroke android:width="1dp" android:color="@color/media_seamless_border"/>
+ <corners android:radius="24dp"/>
+ </shape>
+ </item>
+</ripple> \ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/qs_media_divider.xml b/packages/SystemUI/res-keyguard/layout/qs_media_divider.xml
new file mode 100644
index 000000000000..1be489cdc700
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/qs_media_divider.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginBottom="16dp"
+ android:background="@color/media_divider">
+</View> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_management.xml b/packages/SystemUI/res/layout/controls_management.xml
index 46f79deff109..ae7f44d19430 100644
--- a/packages/SystemUI/res/layout/controls_management.xml
+++ b/packages/SystemUI/res/layout/controls_management.xml
@@ -69,7 +69,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
- android:text="See other apps"
+ android:text="@string/controls_favorite_see_other_apps"
style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
diff --git a/packages/SystemUI/res/layout/media_carousel.xml b/packages/SystemUI/res/layout/media_carousel.xml
index dc917316bef1..ee1173be0db9 100644
--- a/packages/SystemUI/res/layout/media_carousel.xml
+++ b/packages/SystemUI/res/layout/media_carousel.xml
@@ -23,7 +23,7 @@
android:clipChildren="false"
android:clipToPadding="false"
>
- <com.android.systemui.media.UnboundHorizontalScrollView
+ <com.android.systemui.media.MediaScrollView
android:id="@+id/media_carousel_scroller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -41,14 +41,12 @@
>
<!-- QSMediaPlayers will be added here dynamically -->
</LinearLayout>
- </com.android.systemui.media.UnboundHorizontalScrollView>
+ </com.android.systemui.media.MediaScrollView>
<com.android.systemui.qs.PageIndicator
android:id="@+id/media_page_indicator"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginBottom="4dp"
- android:layout_gravity="center_horizontal|bottom"
- android:gravity="center"
android:tint="@color/media_primary_text"
/>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/media_carousel_settings_button.xml b/packages/SystemUI/res/layout/media_carousel_settings_button.xml
new file mode 100644
index 000000000000..4570cb1d1d10
--- /dev/null
+++ b/packages/SystemUI/res/layout/media_carousel_settings_button.xml
@@ -0,0 +1,29 @@
+<?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.
+ -->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/settings_cog"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@string/controls_media_settings_button"
+ android:paddingStart="30dp"
+ android:paddingEnd="30dp"
+ android:paddingBottom="20dp"
+ android:paddingTop="20dp"
+ android:src="@drawable/ic_settings"
+ android:tint="@color/notification_gear_color"
+ android:visibility="invisible"
+ android:forceHasOverlappingRendering="false"/>
diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml
index c17b0c8580ca..07bbb8f40eb8 100644
--- a/packages/SystemUI/res/layout/media_view.xml
+++ b/packages/SystemUI/res/layout/media_view.xml
@@ -26,6 +26,7 @@
android:gravity="center_horizontal|fill_vertical"
android:background="@drawable/qs_media_background">
+ <!-- As per Material Design on Biderectionality, this is forced to LTR in code -->
<FrameLayout
android:id="@+id/notification_media_progress_time"
android:layout_width="0dp"
@@ -36,7 +37,7 @@
android:id="@+id/media_elapsed_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textColor="@color/media_primary_text"
android:gravity="start"
@@ -46,13 +47,36 @@
android:id="@+id/media_total_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textColor="@color/media_primary_text"
android:gravity="end"
android:textSize="14sp" />
</FrameLayout>
+ <!-- Actions must be ordered left-to-right even in RTL layout. However, they appear in a chain
+ with the album art and the title, and must as a group appear at the end of that chain. This is
+ accomplished by having the guidebox (an invisible view that is positioned around all 5 actions)
+ in the chain with the album art and the title. The actions are in a LTR chain bounded by that
+ guidebox, and the ambiguity of how wide the guidebox should be is resolved by using a barrier
+ which forces it's starting edge to be as far to the end as possible while fitting the actions.
+ -->
+ <androidx.constraintlayout.widget.Barrier
+ android:id="@+id/media_action_barrier"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="vertical"
+ app:barrierDirection="start"
+ />
+
+ <View
+ android:id="@+id/media_action_guidebox"
+ android:layout_width="0dp"
+ android:layout_height="48dp"
+ android:layout_marginTop="16dp"
+ android:visibility="invisible"
+ />
+
<ImageButton
android:id="@+id/action0"
style="@style/MediaPlayer.Button"
@@ -94,20 +118,20 @@
android:id="@+id/media_seamless"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:foreground="@*android:drawable/media_seamless_background"
+ android:foreground="@drawable/qs_media_seamless_background"
android:background="@drawable/qs_media_light_source"
android:orientation="horizontal"
android:forceHasOverlappingRendering="false"
- android:paddingLeft="12dp"
+ android:paddingStart="12dp"
android:paddingTop="6dp"
- android:paddingRight="12dp"
+ android:paddingEnd="12dp"
android:paddingBottom="6dp">
<ImageView
android:id="@+id/media_seamless_image"
android:layout_width="@dimen/qs_seamless_icon_size"
android:layout_height="@dimen/qs_seamless_icon_size"
- android:layout_marginRight="8dp"
+ android:layout_marginEnd="8dp"
android:tint="@color/media_primary_text"
android:src="@*android:drawable/ic_media_seamless" />
@@ -115,10 +139,11 @@
android:id="@+id/media_seamless_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
android:singleLine="true"
android:text="@*android:string/ext_media_seamless_action"
android:textColor="@color/media_primary_text"
+ android:textDirection="locale"
android:textSize="14sp" />
</LinearLayout>
@@ -140,13 +165,14 @@
/>
<!-- Seek Bar -->
+ <!-- As per Material Design on Biderectionality, this is forced to LTR in code -->
<SeekBar
android:id="@+id/media_progress_bar"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:clickable="true"
- android:maxHeight="3dp"
+ android:maxHeight="@dimen/qs_media_enabled_seekbar_height"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:thumbTint="@color/media_primary_text"
@@ -161,6 +187,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
+ android:textDirection="locale"
android:textSize="14sp" />
<!-- Song name -->
@@ -171,6 +199,7 @@
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:singleLine="true"
android:textColor="@color/media_primary_text"
+ android:textDirection="locale"
android:textSize="16sp" />
<!-- Artist name -->
@@ -178,16 +207,17 @@
android:id="@+id/header_artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
android:singleLine="true"
android:textColor="@color/media_secondary_text"
+ android:textDirection="locale"
android:textSize="14sp" />
<com.android.internal.widget.CachingIconView
android:id="@+id/icon"
android:tint="@color/media_primary_text"
- android:layout_width="16dp"
- android:layout_height="16dp" />
+ android:layout_width="20dp"
+ android:layout_height="20dp" />
<!-- Buttons to remove this view when no longer needed -->
<include
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 761ab03ee87e..597644bf3295 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -62,6 +62,8 @@
android:focusable="true"
android:accessibilityTraversalBefore="@android:id/edit">
<include layout="@layout/qs_footer_impl" />
+ <include layout="@layout/qs_media_divider"
+ android:id="@+id/divider"/>
</com.android.systemui.qs.QSPanel>
</com.android.systemui.qs.NonInterceptingScrollView>
diff --git a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
index cd90efe9a215..1d2340dadb8a 100644
--- a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
+++ b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
@@ -45,7 +45,7 @@
android:id="@+id/icon_mic"
android:layout_width="35dp"
android:layout_height="35dp"
- android:layout_marginLeft="6dp"
+ android:layout_marginStart="6dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp">
@@ -112,7 +112,7 @@
</FrameLayout>
<View
- android:id="@+id/bg_right"
+ android:id="@+id/bg_end"
android:layout_width="12dp"
android:layout_height="47dp"
android:background="@drawable/tv_rect_dark_right_rounded"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ac1229632758..bdff23560d52 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tik weer om oop te maak"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swiep op om oop te maak"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swiep op om weer te probeer"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Hierdie toestel behoort aan jou organisasie"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swiep vanaf ikoon vir foon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Swiep vanaf ikoon vir stembystand"</string>
<string name="camera_hint" msgid="4519495795000658637">"Swiep vanaf ikoon vir kamera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiel kan gemonitor word"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Netwerk kan dalk gemonitor word"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Netwerk kan dalk gemonitor word"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Jou organisasie besit hierdie toestel en kan netwerkverkeer monitor"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> besit hierdie toestel en kan netwerkverkeer monitor"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Hierdie toestel behoort aan jou organisasie en is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> en is gekoppel aan <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Hierdie toestel behoort aan jou organisasie"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Hierdie toestel behoort aan jou organisasie en is gekoppel aan VPN\'e"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> en is gekoppel aan VPN\'e"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Jou organisasie kan netwerkverkeer in jou werkprofiel monitor"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kan netwerkverkeer in jou werkprofiel monitor"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Netwerk kan gemonitor word"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Hierdie toestel is gekoppel aan VPN\'e"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Jou werkprofiel is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Jou persoonlike profiel is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Hierdie toestel is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Toestelbestuur"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Profielmonitering"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Netwerkmonitering"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktiveer VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Ontkoppel VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Bekyk beleide"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nJou IT-admin kan instellings, korporatiewe toegang, programme, data wat met jou toestel geassosieer word, en jou toestel se ligginginligting monitor en bestuur.\n\nKontak jou IT-admin vir meer inligting."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Hierdie toestel behoort aan jou organisasie.\n\nJou IT-admin kan instellings, korporatiewe toegang, programme, data wat met jou toestel geassosieer word, en jou toestel se ligginginligting monitor en bestuur.\n\nKontak jou IT-admin vir meer inligting."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Jou organisasie het \'n sertifikaatoutoriteit op hierdie toestel geïnstalleer. Jou veilige netwerkverkeer kan gemonitor of gewysig word."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Jou organisasie het \'n sertifikaatoutoriteit in jou werkprofiel geïnstalleer. Jou veilige netwerkverkeer kan gemonitor of gewysig word."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"\'n Sertifikaatoutoriteit is op hierdie toestel geïnstalleer. Jou veilige netwerkverkeer kan gemonitor of gewysig word."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Laat wag"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Slaan oor na volgende"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Slaan oor na vorige"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Verander grootte"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Foon afgeskakel weens hitte"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Jou foon werk nou normaal"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Jou foon was te warm en dit het afgeskakel om af te koel. Jou foon werk nou normaal.\n\nJou foon kan dalk te warm word as jy:\n • Hulpbron-intensiewe programme (soos dobbel-, video- of navigasieprogramme) gebruik\n • Groot lêers af- of oplaai\n • Jou foon in hoë temperature gebruik"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Bevestig verandering vir <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swiep om meer te sien"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laai tans aanbevelings"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Versteek die huidige sessie."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Versteek"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fout, probeer tans weer …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie gekry nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d6aa2ee56bd8..d4c2380bbe43 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"ባለበት አቁም"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"ወደ ቀጣይ ዝለል"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"ወደ ቀዳሚ ዝለል"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"መጠን ይቀይሩ"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"ስልክ በሙቀት ምክንያት ጠፍቷል"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"የእርስዎ ስልክ አሁን በመደበኝነት እያሄደ ነው"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"የእርስዎ ስልክ በጣም ግሎ ነበር፣ ስለዚህ እንዲቀዘቅዝ ጠፍቷል። የእርስዎ ስልክ አሁን በመደበኝነት እያሄደ ነው።\n\nየሚከተሉትን ካደረጉ የእርስዎ በጣም ሊግል ይችላል፦\n • ኃይል በጣም የሚጠቀሙ መተግበሪያዎችን (እንደ ጨዋታ፣ ቪዲዮ ወይም የአሰሳ መተግበሪያዎች ያሉ) ከተጠቀሙ\n • ትላልቅ ፋይሎችን ካወረዱ ወይም ከሰቀሉ\n • ስልክዎን በከፍተኛ ሙቀት ውስጥ ከተጠቀሙ"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"ለ<xliff:g id="DEVICE">%s</xliff:g> ለውጥን ያረጋግጡ"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ተጨማሪ ለማየት ያንሸራትቱ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ምክሮችን በመጫን ላይ"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"ሚዲያ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"የአሁኑን ክፍለ-ጊዜ ደብቅ።"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ደብቅ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</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>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 9dcfb5f294c8..806408af4d75 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -956,8 +956,7 @@
<string name="pip_pause" msgid="1139598607050555845">"إيقاف مؤقت"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"التخطي إلى التالي"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"التخطي إلى السابق"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"تغيير الحجم"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"تم إيقاف الهاتف بسبب الحرارة"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"يعمل هاتفك الآن بشكل طبيعي"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"ارتفعت درجة حرارة هاتفك بشدة، لذا تم إيقاف تشغيله لخفض درجة حرارته. يعمل هاتفك الآن بشكل طبيعي.\n\nقد ترتفع بشدة درجة حرارة هاتفك إذا:\n • استخدمت تطبيقات كثيفة الاستخدام لموارد الجهاز (مثل الألعاب أو الفيديو أو تطبيقات التنقل)\n • نزَّلت أو حمَّلت ملفات كبيرة الحجم\n • استخدمت هاتفك وسط أجواء مرتفعة الحرارة"</string>
@@ -1104,15 +1103,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"تأكيد التغيير لـ <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"مرّر سريعًا لرؤية المزيد."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"الوسائط"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"إخفاء الجلسة الحالية"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"إخفاء"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"استئناف التشغيل"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"الإعدادات"</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>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index ae01daedee8d..25c87fbd3bb0 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>ৰ বাবে সলনি কৰাটো নিশ্চিত কৰক"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"অধিক চাবলৈ ছোৱাইপ কৰক"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"বৰ্তমানৰ ছেশ্বনটো লুকুৱাওক।"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকুৱাওক"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</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>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index fc91cb2c3613..cfde8a6c23bd 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Fasilə verin"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Növbətiyə keçin"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Əvvəlkinə keçin"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Ölçüsünü dəyişin"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"İstiliyə görə telefon söndü"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefon indi normal işləyir"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon çox isti idi və soyumaq üçün söndü. Hazırda telefon normal işləyir.\n\n Telefon bu hallarda çox isti ola bilər:\n • Çox resurslu tətbiq istifadə etsəniz (oyun, video və ya naviqasiya tətbiqi kimi)\n • Böyük həcmli fayl endirsəniz və ya yükləsəniz\n • Telefonu yüksək temperaturda istifadə etsəniz"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 9006e03b287f..50aba93d30a1 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -456,10 +456,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite ponovo da biste otvorili"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite nagore da biste otvorili"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Prevucite nagore da biste probali ponovo"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada organizaciji"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Prevucite od ikone za telefon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Prevucite od ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="4519495795000658637">"Prevucite od ikone za kameru"</string>
@@ -526,33 +524,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil se možda nadgleda"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Mreža se možda nadgleda"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Mreža se možda nadgleda"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizacija je vlasnik uređaja i može da nadgleda mrežni saobraćaj"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> je vlasnik ovog uređaja i može da nadgleda mrežni saobraćaj"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ovaj uređaj pripada organizaciji i povezan je sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je sa aplikacijom <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Ovaj uređaj pripada organizaciji"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Ovaj uređaj pripada organizaciji i povezan je sa VPN-ovima"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je sa VPN-ovima"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Organizacija može da prati mrežni saobraćaj na poslovnom profilu"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> može da nadgleda mrežni saobraćaj na poslovnom profilu"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Mreža se možda nadgleda"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Ovaj uređaj je povezan sa VPN-ovima"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Poslovni profil je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Vaš lični profil je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Ovaj uređaj je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Upravljanje uređajima"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Nadgledanje profila"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Nadgledanje mreže"</string>
@@ -562,10 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Onemogući VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini vezu sa VPN-om"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži smernice"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT administrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima.\n\nViše informacija potražite od IT administratora."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Ovaj uređaj pripada organizaciji.\n\nIT administrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima.\n\nViše informacija potražite od IT administratora."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizacija je na ovom uređaju instalirala autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizacija je na poslovnom profilu instalirala autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Na ovom uređaju je instaliran autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
@@ -941,8 +925,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pauziraj"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Pređi na sledeće"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Pređi na prethodno"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Promenite veličinu"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon se isključio zbog toplote"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefon sada normalno radi"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon je bio prevruć, pa se isključio da se ohladi. Sada radi normalno.\n\nTelefon može previše da se ugreje ako:\n • Koristite aplikacije koje zahtevaju puno resursa (npr. video igre, video ili aplikacije za navigaciju)\n • Preuzimate/otpremate velike datoteke\n • Koristite telefon na visokoj temperaturi"</string>
@@ -1086,15 +1069,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdite promenu za: <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Prevucite da biste videli još"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavaju se preporuke"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte aktuelnu sesiju."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Greška, pokušava se ponovo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index d32cc9add75c..83b58106523f 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -946,8 +946,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Прыпыніць"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Перайсці да наступнага"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Перайсці да папярэдняга"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Змяніць памер"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"З-за перагрэву тэл. выключыўся"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Тэлефон працуе нармальна"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Ваш тэлефон пераграваўся, таму ён выключыўся, каб астыць. Зараз тэлефон працуе нармальна.\n\nТэлефон можа перагравацца пры:\n • Выкарыстанні рэсурсаёмістых праграм (напрыклад, гульняў, відэа або праграм навігацыі)\n • Спампоўцы або запампоўцы вялікіх файлаў\n • Выкарыстанні тэлефона пры высокіх тэмпературах"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index ff950d57f6e9..9d6a2bf83a88 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Докоснете отново, за да отворите"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Прекарайте пръст нагоре, за да отключите"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Плъзнете бързо нагоре, за да опитате отново"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Това устройство принадлежи на организацията ви"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Плъзнете с пръст от иконата, за да използвате телефона"</string>
<string name="voice_hint" msgid="7476017460191291417">"Прекарайте пръст от иконата, за да получите гласова помощ"</string>
<string name="camera_hint" msgid="4519495795000658637">"Плъзнете с пръст от иконата, за да включите камерата"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Възможно е потребителският профил да се наблюдава"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Мрежата може да се наблюдава"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Мрежата може да се наблюдава"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организацията ви притежава това устройство и може да наблюдава трафика в мрежата"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> притежава това устройство и може да наблюдава трафика в мрежата"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Това устройство принадлежи на организацията ви и е свързано с(ъс) <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> и е свързано с(ъс) <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Това устройство принадлежи на организацията ви"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Това устройство принадлежи на организацията ви и е свързано с виртуални частни мрежи (VPN)"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> и е свързано с виртуални частни мрежи (VPN)"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Организацията ви може да наблюдава трафика в мрежата в служебния ви потребителски профил"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> може да наблюдава трафика в мрежата в служебния ви потребителски профил"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Мрежата може да се наблюдава"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Това устройство е свързано с виртуални частни мрежи (VPN)"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Служебният ви потребителски профил е свързан с(ъс) <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Личният ви потребителски профил е свързан с(ъс) <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Това устройство е свързано с(ъс) <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Управление на устройствата"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Наблюдаване на потр. профил"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Наблюдение на мрежата"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Деактивиране на VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Прекратяване на връзката с VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Преглед на правилата"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nСистемният ви администратор може да наблюдава и управлява настройките, корпоративния достъп, приложенията, свързаните с устройството данни и информацията за местоположението му.\n\nЗа повече информация се обърнете към него."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Това устройство принадлежи на организацията ви.\n\nСистемният ви администратор може да наблюдава и управлява настройките, корпоративния достъп, приложенията, свързаните с устройството данни и информацията за местоположението му.\n\nЗа повече информация се обърнете към него."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Организацията ви е инсталирала сертифициращ орган на това устройство. Трафикът в защитената ви мрежа може да бъде наблюдаван или променян."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Организацията ви е инсталирала сертифициращ орган в служебния ви потребителски профил. Трафикът в защитената ви мрежа може да бъде наблюдаван или променян."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На това устройство е инсталиран сертифициращ орган. Трафикът в защитената ви мрежа може да бъде наблюдаван или променян."</string>
@@ -1079,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Потвърдете промяната за <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Прекарайте пръст, за да видите повече"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Препоръките се зареждат"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Мултимедия"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Скриване на текущата сесия."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Скриване"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</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>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 557b4e37bd12..e204bc8856ad 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>-এর জন্য পরিবর্তন কনফার্ম করুন"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"আরও দেখতে সোয়াইপ করুন"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"বর্তমান সেশন লুকান।"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকান"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</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>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index d3190318237b..f9c92e5a2c8d 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -456,10 +456,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite ponovo da otvorite"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite da otvorite"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Prevucite preko ikone da otvorite telefon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Prevucite preko ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="4519495795000658637">"Prevucite od ikone da otvorite kameru"</string>
@@ -526,33 +524,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil može biti nadziran"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Mreža može biti nadzirana"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Mreža može biti nadzirana"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizacija je vlasnik ovog uređaja i može nadzirati mrežni saobraćaj"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može nadzirati mrežni saobraćaj"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ovaj uređaj pripada vašoj organizaciji i povezan je s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je s aplikacijom <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Ovaj uređaj pripada vašoj organizaciji"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Ovaj uređaj pripada vašoj organizaciji i povezan je s VPN-ovima"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je VPN-ovima"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Vaša organizacija može pratiti mrežni saobraćaj na vašem profilu."</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> može pratiti mrežni saobraćaj na vašem radnom profilu"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Mreža može biti nadzirana"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Ovaj uređaj je povezan VPN-ovima"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Vaš radni profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Vaš lični profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Ovaj uređaj je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Upravljanje uređajem"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Praćenje profila"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Praćenje mreže"</string>
@@ -562,10 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Isključi VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini VPN vezu"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži pravila"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVaš IT administrator može nadzirati postavke, korporativni pristup, aplikacije, podatke povezane s vašim uređajem i informacije o lokaciji uređaja te njima upravljati.\n\nZa više informacija, kontaktirajte IT administratora."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Ovaj uređaj pripada vašoj organizaciji.\n\nVaš IT administrator može nadzirati postavke, korporativni pristup, aplikacije, podatke povezane s vašim uređajem i informacije o lokaciji uređaja te njima upravljati.\n\nZa više informacija, kontaktirajte IT administratora."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Vaša organizacija je instalirala CA certifikat na ovom uređaju. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Vaša organizacija je instalirala CA certifikat na vašem radnom profilu. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"CA certifikat je instaliran na ovom uređaju. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
@@ -943,8 +927,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pauziraj"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Preskoči na sljedeći"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Preskoči na prethodni"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Promjena veličine"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon se isključio zbog pregrijavanja"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Vaš telefon sada radi normalno"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Vaš telefon se pregrijao, pa se isključio da se ohladi. Telefon sada radi normalno.\n\nTelefon se može pregrijati ako:\n • Koristite aplikacije koje troše puno resursa (kao što su aplikacije za igranje, videozapise ili navigaciju)\n • Preuzimate ili otpremate velike fajlove\n • Koristite telefon na visokim temperaturama"</string>
@@ -1088,15 +1071,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdite promjenu za uređaj <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Prevucite da vidite više"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte trenutnu sesiju."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Greška, ponovni pokušaj…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index a8c7c26c8bca..0315e3fa861a 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Torna a tocar per obrir-la."</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Llisca cap amunt per obrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Llisca cap a dalt per tornar-ho a provar"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Aquest dispositiu pertany a la teva organització"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Aquest dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Llisca des de la icona per obrir el telèfon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Llisca des de la icona per obrir l\'assistent de veu"</string>
<string name="camera_hint" msgid="4519495795000658637">"Llisca des de la icona per obrir la càmera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"El perfil es pot supervisar"</string>
<string name="vpn_footer" msgid="3457155078010607471">"És possible que la xarxa estigui supervisada."</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"És possible que la xarxa estigui supervisada"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"La teva organització és propietària del dispositiu i és possible que supervisi el trànsit de xarxa"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> és propietària d\'aquest dispositiu i és possible que supervisi el trànsit de xarxa"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Aquest dispositiu pertany a la teva organització i està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Aquest dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i està connectat a <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Aquest dispositiu pertany a la teva organització"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Aquest dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Aquest dispositiu pertany a la teva organització i està connectat a xarxes VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Aquest dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i està connectat a xarxes VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"És possible que la teva organització supervisi el trànsit de xarxa al teu perfil de treball"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"És possible que <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> supervisi el trànsit de xarxa del teu perfil de treball"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"És possible que la xarxa estigui supervisada"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Aquest dispositiu està connectat a xarxes VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"El teu perfil de treball està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"El teu perfil personal està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Aquest dispositiu està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gestió del dispositiu"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Supervisió del perfil"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Supervisió de la xarxa"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Desactiva la VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconnecta la VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Consulta les polítiques"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"El dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nL\'administrador de TI pot supervisar i gestionar la configuració, l\'accés corporatiu, les aplicacions, les dades associades al dispositiu i la informació d\'ubicació.\n\nPer obtenir més informació, contacta amb l\'administrador de TI."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"El dispositiu pertany a la teva organització.\n\nL\'administrador de TI pot supervisar i gestionar la configuració, l\'accés corporatiu, les aplicacions, les dades associades al dispositiu i la informació d\'ubicació.\n\nPer obtenir més informació, contacta amb l\'administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"La teva organització ha instal·lat una autoritat de certificació en aquest dispositiu. És possible que el trànsit a la xarxa segura se supervisi o es modifiqui."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"La teva organització ha instal·lat una autoritat de certificació al teu perfil de treball. És possible que el trànsit de xarxa segura se supervisi o es modifiqui."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"S\'ha instal·lat una autoritat de certificació en aquest dispositiu. És possible que el trànsit de xarxa segura se supervisi o es modifiqui."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Posa en pausa"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Ves al següent"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Torna a l\'anterior"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Canvia la mida"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telèfon apagat per la calor"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Ara el telèfon funciona de manera normal"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"El telèfon s\'havia sobreescalfat i s\'ha apagat per refredar-se. Ara funciona amb normalitat.\n\nEs pot sobreescalfar si:\n • utilitzes aplicacions que consumeixen molts recursos (com ara, videojocs, vídeos o aplicacions de navegació);\n • baixes o penges fitxers grans;\n • l\'utilitzes amb temperatures altes."</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirma el canvi per a <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Llisca per veure\'n més"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregant les recomanacions"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Multimèdia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Amaga la sessió actual."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Amaga"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error. S\'està tornant a provar…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No s\'ha trobat"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 60e584c9a8eb..aa5401edf301 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -458,10 +458,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Oznámení otevřete opětovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Otevřete přejetím prstem nahoru"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Přejetím nahoru to zkusíte znovu"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zařízení patří vaší organizaci"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefon otevřete přejetím prstem od ikony"</string>
<string name="voice_hint" msgid="7476017460191291417">"Hlasovou asistenci otevřete přejetím prstem od ikony"</string>
<string name="camera_hint" msgid="4519495795000658637">"Fotoaparát otevřete přejetím prstem od ikony"</string>
@@ -529,33 +527,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil může být monitorován"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Síť může být sledována"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Síť může být monitorována"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Toto zařízení vlastní vaše organizace, která může sledovat síťový provoz"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Toto zařízení spravuje organizace <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, která může sledovat síťový provoz"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Toto zařízení patří vaší organizaci a je připojené k síti <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> a je připojené k síti <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Toto zařízení patří vaší organizaci"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Toto zařízení patří vaší organizaci a je připojené k sítím VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> a je připojené k sítím VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Organizace může ve vašem pracovním profilu sledovat síťový provoz"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> může ve vašem pracovním profilu sledovat síťový provoz"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Síť může být sledována"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Toto zařízení je připojené k sítím VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Váš pracovní profil je připojen k síti <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Váš osobní profil je připojený k síti <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Toto zařízení je připojené k síti <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Správa zařízení"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Monitoring profilu"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Sledování sítě"</string>
@@ -565,10 +551,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktivovat VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Odpojit VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Zobrazit zásady"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVáš administrátor IT může sledovat a spravovat nastavení, firemní přístup, aplikace, data přidružená k tomuto zařízení a jeho polohu.\n\nDalší informace vám poskytne váš administrátor IT."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Toto zařízení patří vaší organizaci\n\nVáš administrátor IT může sledovat a spravovat nastavení, firemní přístup, aplikace, data přidružená k tomuto zařízení a jeho polohu.\n\nDalší informace vám poskytne váš administrátor IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizace do tohoto zařízení nainstalovala certifikační autoritu. Zabezpečený síťový provoz může být sledován nebo upravován."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizace do vašeho pracovního profilu nainstalovala certifikační autoritu. Zabezpečený síťový provoz může být sledován nebo upravován."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"V zařízení je nainstalována certifikační autorita. Zabezpečený síťový provoz může být sledován nebo upravován."</string>
@@ -946,8 +930,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pozastavit"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Přeskočit na další"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Přeskočit na předchozí"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Změnit velikost"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon se vypnul z důvodu zahřátí"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Nyní telefon funguje jako obvykle."</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon byl příliš zahřátý, proto se vypnul, aby vychladl. Nyní telefon funguje jako obvykle.\n\nTelefon se může příliš zahřát v těchto případech:\n • používání náročných aplikací (např. her, videí nebo navigace),\n • stahování nebo nahrávání velkých souborů,\n • používání telefonu při vysokých teplotách."</string>
@@ -1092,15 +1075,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Ověřte změnu v zařízení <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Přejetím prstem zobrazíte další položky"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítání doporučení"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Skrýt aktuální relaci."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrýt"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Chyba. Nový pokus…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenalezeno"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f07e8605fb23..0bd63587f6e7 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tryk igen for at åbne"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Stryg opad for at åbne"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Stryg fra telefonikonet"</string>
<string name="voice_hint" msgid="7476017460191291417">"Stryg fra mikrofonikonet"</string>
<string name="camera_hint" msgid="4519495795000658637">"Stryg fra kameraikonet"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilen kan overvåges"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Netværket kan være overvåget"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Netværket kan være overvåget"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Din organisation ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Denne enhed tilhører din organisation og har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og har forbindelse til <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Denne enhed tilhører din organisation"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Denne enhed tilhører din organisation og har forbindelse til VPN-netværk"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og har forbindelse til VPN-netværk"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Din organisation kan overvåge netværkstrafikken på din arbejdsprofil"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kan overvåge netværkstrafik på din arbejdsprofil"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Netværket kan være overvåget"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Denne enhed har forbindelse til VPN-netværk"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Din arbejdsprofil har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Din personlige profil har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Denne enhed har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Administration af enheder"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Profilovervågning"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Overvågning af netværk"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktiver VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Afbryd VPN-forbindelse"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Se politikker"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Denne enhed tilhører din organisation.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Din organisation har installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Din organisation har installeret et nøglecenter på din arbejdsprofil. Din sikre netværkstrafik kan overvåges eller ændres."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Der er installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Sæt på pause"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Gå videre til næste"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Gå til forrige"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Rediger størrelse"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefonen slukkede pga. varme"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Din telefon kører nu normalt"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Din telefon var blevet for varm, så den slukkede for at køle ned. Din telefon kører nu igen normalt. \n\nDin telefon kan blive for varm, hvis du:\n • Bruger ressourcekrævende apps (f.eks. spil, video eller navigation)\n • Downloader eller uploader store filer\n • Bruger din telefon i varme omgivelser"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Bekræft ændring på <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Stryg for at se mere"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Indlæser anbefalinger"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Medie"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den aktuelle session."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fejl. Prøver igen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 642503afeda4..f7323bcaae17 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausieren"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Vorwärts springen"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Rückwärts springen"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Größe anpassen"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Ausgeschaltet, da zu heiß"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Dein Smartphone funktioniert jetzt wieder normal"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Dein Smartphone war zu heiß und wurde zum Abkühlen ausgeschaltet. Nun funktioniert es wieder normal.\n\nMögliche Ursachen:\n • Verwendung ressourcenintensiver Apps (z. B. Spiele-, Video- oder Navigations-Apps)\n • Download oder Upload großer Dateien \n • Verwendung des Smartphones bei hohen Temperaturen"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Änderung für <xliff:g id="DEVICE">%s</xliff:g> bestätigen"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Wischen, um weitere zu sehen"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Medien"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Du kannst die aktuelle Sitzung ausblenden."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ausblenden"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fehler. Neuer Versuch…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nicht gefunden"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index d916327ecccc..84ae32324e88 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Πατήστε ξανά για να ανοίξετε"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Σύρετε προς τα επάνω για άνοιγμα"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Σύρετε προς τα πάνω για να δοκιμάσετε ξανά"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Σύρετε προς τα έξω για τηλέφωνο"</string>
<string name="voice_hint" msgid="7476017460191291417">"Σύρετε προς τα έξω για voice assist"</string>
<string name="camera_hint" msgid="4519495795000658637">"Σύρετε προς τα έξω για κάμερα"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Το προφίλ ενδέχεται να παρακολουθείται"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ο οργανισμός σας κατέχει αυτήν τη συσκευή και μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου."</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Ο οργανισμός <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> κατέχει αυτήν τη συσκευή και μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου."</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Αυτή η συσκευή ανήκει στον οργανισμό σας και είναι συνδεδεμένη στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> και είναι συνδεδεμένη στην εφαρμογή <xliff:g id="VPN_APP">%2$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Αυτή η συσκευή ανήκει στον οργανισμό σας και είναι συνδεδεμένη σε ορισμένα VPN."</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> και είναι συνδεδεμένη σε ορισμένα VPN."</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Ο οργανισμός σας μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου στο προφίλ εργασίας σας"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Ο οργανισμός <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου στο προφίλ εργασίας σας"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Αυτή η συσκευή είναι συνδεδεμένη σε ορισμένα VPN."</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Το προφίλ εργασίας σας είναι συνδεδεμένο στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Το προσωπικό σας προφίλ είναι συνδεδεμένο στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Αυτή η συσκευή είναι συνδεδεμένη στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Διαχείριση συσκευών"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Παρακολούθηση προφίλ"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Παρακολούθηση δικτύου"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Απενεργοποίηση VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Αποσύνδεση VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Προβολή πολιτικών"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nΟ διαχειριστής IT μπορεί να παρακολουθεί και να διαχειρίζεται τις ρυθμίσεις, την εταιρική πρόσβαση, τις εφαρμογές, τα δεδομένα που σχετίζονται με τη συσκευή καθώς και τις πληροφορίες τοποθεσίας της συσκευής σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή IT."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Αυτή η συσκευή ανήκει στον οργανισμό σας.\n\nΟ διαχειριστής IT μπορεί να παρακολουθεί και να διαχειρίζεται τις ρυθμίσεις, την εταιρική πρόσβαση, τις εφαρμογές, τα δεδομένα που σχετίζονται με τη συσκευή καθώς και τις πληροφορίες τοποθεσίας της συσκευής σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ο οργανισμός σας εγκατέστησε μια αρχή έκδοσης πιστοποιητικών σε αυτήν τη συσκευή. Η ασφαλής επισκεψιμότητα δικτύου σας μπορεί να παρακολουθείται ή να τροποποιείται."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ο οργανισμός σας εγκατέστησε μια αρχή έκδοσης πιστοποιητικών στο προφίλ εργασίας σας. Η ασφαλής επισκεψιμότητα δικτύου σας μπορεί να παρακολουθείται ή να τροποποιείται."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Μια αρχή έκδοσης πιστοποιητικών έχει εγκατασταθεί σε αυτήν τη συσκευή. Η ασφαλής επισκεψιμότητα δικτύου σας μπορεί να παρακολουθείται ή να τροποποιείται."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Παύση"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Μετάβαση στο επόμενο"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Μετάβαση στο προηγούμενο"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Αλλαγή μεγέθους"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Το τηλέφωνο απεν. λόγω ζέστης"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Το τηλέφωνο λειτουργεί πλέον κανονικά"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Η θερμοκρασία του τηλεφώνου είναι πολύ υψηλή και απενεργοποιήθηκε για να κρυώσει. Πλέον, λειτουργεί κανονικά.\n\nΗ θερμοκρασία ενδέχεται να ανέβει κατά τη:\n • Χρήση εφαρμογών υψηλής κατανάλωσης πόρων (όπως gaming, βίντεο ή περιήγησης)\n • Λήψη/μεταφόρτωση μεγάλων αρχείων\n • Χρήση σε υψηλές θερμοκρασίες"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Επιβεβαίωση αλλαγής για <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Σύρετε για να δείτε περισσότερα."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Φόρτωση προτάσεων"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Μέσα"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Απόκρυψη της τρέχουσας περιόδου λειτουργίας."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Απόκρυψη"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</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>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 32ab16635b93..47d708c56052 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1063,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 03a43bb652a9..a69b4a70ebd5 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1063,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 32ab16635b93..47d708c56052 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1063,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 32ab16635b93..47d708c56052 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1063,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirm change for <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 539ee0da6384..ee3a304a9bb4 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1063,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‎Confirm change for ‎‏‎‎‏‏‎<xliff:g id="DEVICE">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎Swipe to see more‎‏‎‎‏‎"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎Loading recommendations‎‏‎‎‏‎"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎Media‎‏‎‎‏‎"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎Hide the current session.‎‏‎‎‏‎"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎Hide‎‏‎‎‏‎"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎Resume‎‏‎‎‏‎"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎Settings‎‏‎‎‏‎"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎Inactive, check app‎‏‎‎‏‎"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎Error, retrying…‎‏‎‎‏‎"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎Not found‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d6bcff10d56f..874b99a9d84c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Presiona de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volver a intentarlo"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Desliza el dedo para desbloquear el teléfono."</string>
<string name="voice_hint" msgid="7476017460191291417">"Desliza el dedo desde el ícono para abrir asistente de voz."</string>
<string name="camera_hint" msgid="4519495795000658637">"Desliza el dedo para acceder a la cámara."</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Es posible que se supervise el perfil."</string>
<string name="vpn_footer" msgid="3457155078010607471">"Es posible que la red esté supervisada."</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Es posible que la red esté supervisada"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Tu organización es propietaria de este dispositivo y podría controlar el tráfico de red"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> es la organización propietaria de este dispositivo y podría controlar el tráfico de red"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertenece a tu organización y está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> y está conectado a <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Este dispositivo pertenece a tu organización"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Este dispositivo pertenece a tu organización y está conectado a VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> y está conectado a VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Tu organización puede controlar el tráfico de red en tu perfil de trabajo"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Es posible que <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> controle el tráfico de red en tu perfil de trabajo"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Es posible que la red esté supervisada"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Este dispositivo está conectado a VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Tu perfil de trabajo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Tu perfil personal está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Este dispositivo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Administración del dispositivo"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Supervisión del perfil"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Supervisión de red"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Inhabilitar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nTu administrador de TI puede controlar y administrar la configuración, el acceso corporativo, las apps, los datos asociados al dispositivo y la información de ubicación.\n\nPara obtener más información, comunícate con el administrador de TI."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertenece a tu organización.\n\nTu administrador de TI puede controlar y administrar la configuración, el acceso corporativo, las apps, los datos asociados al dispositivo y la información de ubicación.\n\nPara obtener más información, comunícate con el administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Tu organización instaló una autoridad de certificación en este dispositivo. Es posible que se controle o modifique el tráfico de tu red segura."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Tu organización instaló una autoridad de certificación en tu perfil de trabajo. Es posible que se controle o modifique el tráfico de tu red segura."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Hay una autoridad de certificación instalada en este dispositivo. Es posible que se controle o modifique el tráfico de tu red segura."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausar"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Siguiente"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Anterior"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Cambiar el tamaño"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"El teléfono se apagó por calor"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Tu teléfono ya funciona correctamente"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Tu teléfono estaba muy caliente y se apagó para enfriarse. Ya funciona correctamente.\n\nTu teléfono puede calentarse en estos casos:\n • Usas apps que consumen muchos recursos (como juegos, videos o navegación).\n • Subes o descargas archivos grandes.\n • Usas el teléfono en condiciones de temperatura alta."</string>
@@ -1034,8 +1017,8 @@
<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">"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_show_avatar_text" msgid="5756291381124091508">"Mostrarán una foto de perfil en pantalla de bloqueo"</string>
+ <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecerán 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>
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuración"</string>
@@ -1075,20 +1058,16 @@
<string name="controls_pin_wrong" msgid="6162694056042164211">"PIN incorrecto"</string>
<string name="controls_pin_verifying" msgid="3755045989392131746">"Verificando…"</string>
<string name="controls_pin_instructions" msgid="6363309783822475238">"Ingresa el PIN"</string>
- <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Probar con otro PIN"</string>
+ <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"Prueba con otro PIN"</string>
<string name="controls_confirmation_confirming" msgid="2596071302617310665">"Confirmando…"</string>
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirmar cambio para <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Desliza el dedo para ver más elementos"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Contenido multimedia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Oculta la sesión actual."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
<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>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 36b5140c3656..91f33feeed3a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toca de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Desliza desde el icono para abrir el teléfono"</string>
<string name="voice_hint" msgid="7476017460191291417">"Desliza desde el icono para abrir asistente de voz"</string>
<string name="camera_hint" msgid="4519495795000658637">"Desliza desde el icono para abrir la cámara"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Es posible que se supervise el perfil"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Puede que la red esté supervisada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Puede que la red esté supervisada"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"El dispositivo pertenece a tu organización, que puede supervisar su tráfico de red"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"El dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, que puede supervisar su tráfico de red"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertenece a tu organización y está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> y está conectado a <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Este dispositivo pertenece a tu organización"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Este dispositivo pertenece a tu organización y está conectado a VPNs"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> y está conectado a VPNs"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Tu organización puede supervisar el tráfico de red de tu perfil de trabajo"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> puede supervisar el tráfico de red de tu perfil de trabajo"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Puede que la red esté supervisada"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Este dispositivo está conectado a VPNs"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Tu perfil de trabajo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Tu perfil personal está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Este dispositivo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Administración de dispositivos"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Supervisión del perfil"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Supervisión de red"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Inhabilitar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"El dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nEl administrador de TI puede supervisar y gestionar los ajustes, el acceso corporativo, las aplicaciones, la información de ubicación del dispositivo y los datos asociados a él.\n\nPara obtener más información, ponte en contacto con el administrador de TI."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"El dispositivo pertenece a tu organización.\n\nEl administrador de TI puede supervisar y gestionar los ajustes, el acceso corporativo, las aplicaciones, la información de ubicación del dispositivo y los datos asociados a él.\n\nPara obtener más información, ponte en contacto con el administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Tu organización ha instalado una entidad de certificación en este dispositivo. Es posible que se supervise o se modifique tu tráfico de red seguro."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Tu organización ha instalado una entidad de certificación en tu perfil de trabajo. Es posible que se supervise o se modifique tu tráfico de red seguro."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Se ha instalado una entidad de certificación en este dispositivo. Es posible que se supervise o se modifique tu tráfico de red seguro."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausar"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Saltar al siguiente"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Volver al anterior"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Cambiar tamaño"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Teléfono apagado por calor"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"El teléfono ahora funciona con normalidad"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"El teléfono se había calentado demasiado y se ha apagado para enfriarse. Ahora funciona con normalidad.\n\nPuede calentarse demasiado si:\n • Usas aplicaciones que consumen muchos recursos (p. ej., apps de juegos, vídeos o navegación)\n • Descargas o subes archivos grandes\n • Lo usas a altas temperaturas"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirma el cambio de <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Desliza el dedo para ver más"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar la sesión."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string>
<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>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 521c512c5b8b..c1aa9eb3eef0 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Avamiseks puudutage uuesti"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Pühkige avamiseks üles"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Uuesti proovimiseks pühkige üles"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"See seade kuulub teie organisatsioonile"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefoni kasutamiseks pühkige ikoonilt eemale"</string>
<string name="voice_hint" msgid="7476017460191291417">"Häälabi kasutamiseks pühkige ikoonilt eemale"</string>
<string name="camera_hint" msgid="4519495795000658637">"Kaamera kasutamiseks pühkige ikoonilt eemale"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiili võidakse jälgida"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Võrku võidakse jälgida"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Võrku võidakse jälgida"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"See seade kuulub teie organisatsioonile ja on ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"See seade kuulub organisatsioonile <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ja on ühendatud rakendusega <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"See seade kuulub teie organisatsioonile"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"See seade kuulub teie organisatsioonile ja on ühendatud VPN-idega"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"See seade kuulub organisatsioonile <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ja on ühendatud VPN-idega"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Teie organisatsioon võib jälgida teie tööprofiilil võrguliiklust"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> võib jälgida võrguliiklust teie tööprofiilil"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Võrku võidakse jälgida"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"See seade on ühendatud VPN-idega"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Teie tööprofiil on ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Teie isiklik profiil on ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"See seade on ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Seadmehaldus"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Profiili jälgimine"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Võrgu jälgimine"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Keela VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Katkesta VPN-i ühendus"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Kuva eeskirjad"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"See seade kuulub organisatsioonile <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT-administraator saab jälgida ning hallata seadeid, ettevõttesisest juurdepääsu, rakendusi, seadmega seotud andmeid ja seadme asukohateavet.\n\nLisateabe saamiseks võtke ühendust IT-administraatoriga."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"See seade kuulub teie organisatsioonile.\n\nIT-administraator saab jälgida ning hallata seadeid, ettevõttesisest juurdepääsu, rakendusi, seadmega seotud andmeid ja seadme asukohateavet.\n\nLisateabe saamiseks võtke ühendust IT-administraatoriga."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Teie organisatsioon installis sellesse seadmesse sertifikaadi volituse. Teie turvalist võrguliiklust võidakse jälgida ja muuta."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Teie organisatsioon installis teie tööprofiilile sertifikaadi volituse. Teie turvalist võrguliiklust võidakse jälgida ja muuta."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Sertifikaadi volitus on sellesse seadmesse installitud. Teie turvalist võrguliiklust võidakse jälgida ja muuta."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Peata"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Järgmise juurde"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Eelmise juurde"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Suuruse muutmine"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Tel. lül. kuumuse tõttu välja"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefon töötab nüüd tavapäraselt"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon oli liiga kuum, seetõttu lülitus see jahtumiseks välja. Telefon töötab nüüd tavapäraselt.\n\nTelefon võib kuumaks minna:\n • ressursse koormavate rakenduste kasutamisel (nt mängu-, video- või navigatsioonirakendused)\n • suurte failide alla-/üleslaadimisel\n • telefoni kasutamisel kõrgel temperatuuril"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Kinnitage seadme <xliff:g id="DEVICE">%s</xliff:g> muudatus"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pühkige sõrmega, et näha rohkem"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Soovituste laadimine"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Meedia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Peidetakse praegune seanss."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Peida"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Viga, proovitakse uuesti …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei leitud"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 39dd83286ed6..74a0e126508c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausatu"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Saltatu hurrengora"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Saltatu aurrekora"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Aldatu tamaina"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Beroegi egoteagatik itzali da"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Orain, ohiko moduan dabil telefonoa"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonoa gehiegi berotu da, eta itzali egin da tenperatura jaisteko. Orain, ohiko moduan dabil.\n\nBerotzearen zergati posibleak:\n • Baliabide asko behar dituzten aplikazioak erabiltzea (adib., jokoak, bideoak edo nabigazio-aplikazioak).\n • Fitxategi handiak deskargatu edo kargatzea.\n • Telefonoa giro beroetan erabiltzea."</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Berretsi <xliff:g id="DEVICE">%s</xliff:g> gailuaren aldaketa"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pasatu hatza aukera gehiago ikusteko"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Multimedia-edukia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Ezkutatu uneko saioa."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ezkutatu"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Errorea. Berriro saiatzen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ez da aurkitu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 40677e2db9e1..7704ae2260ce 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"دوباره ضربه بزنید تا باز شود"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند به بالا بکشید"</string>
<string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند به بالا بکشید"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> تعلق دارد"</string>
<string name="phone_hint" msgid="6682125338461375925">"انگشتتان را از نماد تلفن تند بکشید"</string>
<string name="voice_hint" msgid="7476017460191291417">"برای «دستیار صوتی»، تند بکشید"</string>
<string name="camera_hint" msgid="4519495795000658637">"انگشتتان را از نماد دوربین تند بکشید"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"شاید نمایه کنترل شود"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ممکن است شبکه کنترل شود"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ممکن است شبکه کنترل شود"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"مالک این دستگاه سازمان شما است و ممکن است ترافیک شبکه را پایش کند"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"مالک این دستگاه <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> است و ممکن است ترافیک شبکه را پایش کند"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"این دستگاه به سازمان شما تعلق دارد و به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> تعلق دارد و به <xliff:g id="VPN_APP">%2$s</xliff:g> متصل است"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"این دستگاه به سازمان شما تعلق دارد"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> تعلق دارد"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"‏این دستگاه به سازمان شما تعلق دارد و به شبکه‌های VPN متصل است"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"‏این دستگاه به <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> تعلق دارد و به VPN متصل است"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"ممکن است سازمان شما ترافیک شبکه را در نمایه کاری‌تان پایش کند"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ممکن است ترافیک شبکه را در نمایه کاری شما پایش کند"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ممکن است شبکه پایش شود"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"‏این دستگاه به شبکه‌های VPN متصل است"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"نمایه کاری به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"نمایه شخصی شما به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"این دستگاه به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"مدیریت دستگاه"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"کنترل نمایه"</string>
<string name="monitoring_title" msgid="4063890083735924568">"کنترل شبکه"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"‏غیرفعال کردن VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"‏قطع اتصال VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"مشاهده خط‌مشی‌ها"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> تعلق دارد.\n\nسرپرست فناوری اطلاعات می‌تواند تنظیمات، دسترسی شرکتی، برنامه‌ها، داده‌های مرتبط با دستگاه، و اطلاعات مکان دستگاهتان را کنترل و مدیریت کند.\n\nبرای اطلاعات بیشتر، با سرپرست فناوری و اطلاعات تماس بگیرید."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"این دستگاه به سازمان شما تعلق دارد.\n\nسرپرست فناوری اطلاعات می‌تواند تنظیمات، دسترسی شرکتی، برنامه‌ها، و داده‌های مرتبط با دستگاه و اطلاعات مکان دستگاهتان را کنترل و مدیریت کند.\n\nبرای اطلاعات بیشتر، با سرپرست فناوری و اطلاعات تماس بگیرید."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"سازمان شما مرجع گواهینامه‌ای در این دستگاه نصب کرده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"سازمان شما مرجع گواهینامه‌ای در نمایه کاری شما نصب کرده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"مرجع گواهینامه‌ای در این دستگاه نصب شده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"توقف موقت"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"رد شدن به بعدی"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"رد شدن به قبلی"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"تغییر اندازه"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"تلفن به علت گرم شدن خاموش شد"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"اکنون تلفنتان عملکرد معمولش را دارد"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"تلفنتان خیلی گرم شده بود، بنابراین خاموش شد تا خنک شود. اکنون تلفنتان عملکرد معمولش را دارد.\n\nتلفنتان خیلی گرم می‌شود، اگر:\n • از برنامه‌های نیازمند پردازش زیاد (مانند بازی، برنامه‌های ویدیویی یا پیمایشی) استفاده کنید\n • فایل‌های بزرگ بارگیری یا بارگذاری کنید\n • در دماهای بالا از تلفنتان استفاده کنید"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"تأیید تغییر مربوط به <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"برای دیدن موارد بیشتر، تند بکشید"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"درحال بار کردن توصیه‌ها"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"رسانه"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"جلسه فعلی پنهان شود."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"پنهان کردن"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</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>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index e68a187f67a1..efdd81bfbbac 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Avaa napauttamalla uudelleen"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Avaa pyyhkäisemällä ylös"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Organisaatiosi omistaa tämän laitteen"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> omistaa tämän laitteen"</string>
<string name="phone_hint" msgid="6682125338461375925">"Avaa puhelu pyyhkäisemällä."</string>
<string name="voice_hint" msgid="7476017460191291417">"Avaa ääniapuri pyyhkäisemällä kuvakkeesta."</string>
<string name="camera_hint" msgid="4519495795000658637">"Avaa kamera pyyhkäisemällä."</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiilia saatetaan valvoa"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Verkkoa saatetaan valvoa"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Verkkoa saatetaan valvoa"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisaatiosi omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Organisaatiosi omistaa laitteen, joka on yhdistetty tähän: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa laitteen, joka on yhdistetty tähän: <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Organisaatiosi omistaa tämän laitteen"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa tämän laitteen"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Organisaatiosi omistaa tämän laitteen, joka on yhdistetty VPN:iin"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa tämän laitteen, joka on yhdistetty VPN:iin"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Organisaatiosi voi valvoa työprofiilisi verkkoliikennettä."</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> voi valvoa työprofiilisi verkkoliikennettä."</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Verkkoa saatetaan valvoa"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Tämä laite on yhdistetty VPN:iin"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Työprofiilisi on yhdistetty tähän: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Henkilökohtainen profiilisi on yhdistetty tähän: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Laite on yhdistetty tähän: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Laitehallinta"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Profiilin valvonta"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Verkon valvonta"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Poista VPN käytöstä"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Katkaise VPN-yhteys"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Näytä säännöt"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa tämän laitteen.\n\nJärjestelmänvalvoja voi valvoa ja muuttaa asetuksia, yrityskäyttöä, sovelluksia sekä laitteeseen yhdistettyjä tietoja ja sen sijaintitietoja.\n\nSaat lisätietoja järjestelmänvalvojalta."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Organisaatiosi omistaa tämän laitteen.\n\nJärjestelmänvalvoja voi valvoa ja muuttaa asetuksia, yrityskäyttöä, sovelluksia sekä laitteeseen yhdistettyjä tietoja ja sen sijaintitietoja.\n\nSaat lisätietoja järjestelmänvalvojalta."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organisaatiosi asensi laitteeseen varmenteen myöntäjän. Suojattua verkkoliikennettäsi voidaan valvoa tai muuttaa."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organisaatiosi lisäsi työprofiiliin varmenteen myöntäjän. Suojattua verkkoliikennettäsi voidaan valvoa tai muuttaa."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Laitteeseen on asennettu varmenteen myöntäjä. Suojattua verkkoliikennettäsi voidaan valvoa tai muuttaa."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Keskeytä"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Siirry seuraavaan"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Siirry edelliseen"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Muuta kokoa"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Puhelin sammui kuumuuden takia"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Puhelimesi toimii nyt normaalisti."</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Puhelimesi oli liian kuuma, joten se sammui. Puhelimesi toimii nyt normaalisti.\n\nPuhelimesi voi kuumentua liikaa, jos\n • käytät paljon resursseja vaativia sovelluksia (esim. pelejä, videoita tai navigointisovelluksia)\n • lataat tai lähetät suuria tiedostoja\n • käytät puhelintasi korkeissa lämpötiloissa."</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Vahvista muutos: <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pyyhkäise nähdäksesi lisää"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ladataan suosituksia"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Piilota nykyinen käyttökerta."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Piilota"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Virhe, yritetään uudelleen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei löydy"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 0f36da70d1f2..5588cf59fde9 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Interrompre"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Passer au suivant"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Revenir au précédent"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Redimensionner"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Tél. éteint car il surchauffait"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Votre téléphone fonctionne maintenant normalement"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Votre téléphone s\'est éteint, car il surchauffait. Il s\'est refroidi et fonctionne normalement.\n\nIl peut surchauffer si vous :\n • Util. des applis utilisant beaucoup de ressources (jeux, vidéo, navigation, etc.)\n • Téléchargez ou téléversez de gros fichiers\n • Utilisez téléphone dans des températures élevées"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index aa5c2eb246e9..6a7e94c65973 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Suspendre"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Passer au contenu suivant"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Passer au contenu précédent"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Redimensionner"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Tél. éteint car il surchauffait"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"À présent, votre téléphone fonctionne normalement"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Votre téléphone s\'est éteint, car il surchauffait. Il s\'est refroidi et fonctionne normalement.\n\nIl peut surchauffer si vous :\n • exécutez applis utilisant beaucoup de ressources (jeux, vidéo, navigation, etc.) ;\n • téléchargez ou importez gros fichiers ;\n • utilisez téléphone à des températures élevées."</string>
@@ -1033,9 +1032,9 @@
<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">"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_show_at_top_text" msgid="1678400241025513541">"Apparaîtront en haut de la liste des conversations"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Afficheront la photo de profil sur l\'écran de verrouillage"</string>
+ <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Apparaîtront sous forme de 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>
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Paramètres"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirmer la modification pour <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Balayer l\'écran pour voir plus d\'annonces"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Masquer"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erreur. Nouvelle tentative…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 5480daae0d66..cfe6d28c46cb 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toca de novo para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Pasa o dedo cara arriba para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Pasa o dedo cara arriba para tentalo de novo"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence á túa organización"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Pasa o dedo desde a icona para acceder ao teléfono"</string>
<string name="voice_hint" msgid="7476017460191291417">"Pasa o dedo desde a icona para acceder ao asistente de voz"</string>
<string name="camera_hint" msgid="4519495795000658637">"Pasa o dedo desde a icona para acceder á cámara"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pódese supervisar"</string>
<string name="vpn_footer" msgid="3457155078010607471">"É posible que se supervise a rede"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"É posible que se supervise a rede"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"A túa organización é propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é a organización propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence á túa organización e está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está conectado a <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Este dispositivo pertence á túa organización"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Este dispositivo pertence á túa organización e está conectado a varias VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está conectado a varias VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"A túa organización pode controlar o tráfico de rede do teu perfil de traballo"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> pode controlar o tráfico de rede do teu perfil de traballo"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"É posible que se controle a rede"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Este dispositivo está conectado a varias VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"O teu perfil de traballo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"O teu perfil persoal está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Este dispositivo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Xestión de dispositivos"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Supervisión do perfil"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Supervisión de rede"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Desactivar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO teu administrador de TI pode supervisar e xestionar a configuración, o acceso corporativo, as aplicacións, os datos asociados co teu dispositivo e a información de localización deste último.\n\nPara obter máis información, contacta co teu administrador de TI."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence á túa organización.\n\nO teu administrador de TI pode supervisar e xestionar a configuración, o acceso corporativo, as aplicacións, os datos asociados co teu dispositivo e a información de localización deste último.\n\nPara obter máis información, contacta co teu administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"A túa organización instalou unha autoridade de certificación neste dispositivo. É posible que se controle ou se modifique o teu tráfico de rede segura."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"A túa organización instalou unha autoridade de certificación no teu perfil de traballo. É posible que se controle ou se modifique o teu tráfico de rede segura."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Este dispositivo ten unha autoridade de certificación instalada. É posible que se controle ou se modifique o teu tráfico de rede segura."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausar"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Ir ao seguinte"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Ir ao anterior"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Cambiar tamaño"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"O teléfono apagouse pola calor"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"O teu teléfono funciona agora con normalidade"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O teléfono estaba moi quente, apagouse para que arrefríe e agora funciona con normalidade.\n\nÉ posible que estea moi quente se:\n • Usas aplicacións que requiren moitos recursos (como aplicacións de navegación, vídeos e xogos)\n • Descargas/cargas ficheiros grandes\n • Usas o teléfono a alta temperatura"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirma o cambio para <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pasar o dedo para ver máis"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendacións"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Contido multimedia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Oculta a sesión actual."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando de novo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Non se atopou"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 56664e6c5763..23f784557c76 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> માટે ફેરફાર કન્ફર્મ કરો"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"વધુ જોવા માટે સ્વાઇપ કરો"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"મીડિયા"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"હાલનું સત્ર છુપાવો."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"છુપાવો"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</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>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index e5835789dacd..28b7f167c0fc 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -938,8 +938,7 @@
<string name="pip_pause" msgid="1139598607050555845">"रोकें"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"अगले पर जाएं"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"पिछले पर जाएं"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"आकार बदलें"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"गर्म होने की वजह से फ़ोन बंद हुआ"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"आपका फ़ोन अब सामान्य रूप से चल रहा है"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"फ़ोन बहुत गर्म हो गया था, इसलिए ठंडा होने के लिए बंद हो गया. फ़ोन अब अच्छे से चल रहा है.\n\nफ़ोन तब बहुत गर्म हो सकता है जब आप:\n • ज़्यादा रिसॉर्स का इस्तेमाल करने वाले ऐप्लिकेशन चलाते हैं (जैसे गेमिंग, वीडियो या नेविगेशन ऐप्लिकेशन)\n • बड़ी फ़ाइलें डाउनलोड या अपलोड करते हैं\n • ज़्यादा तापमान में फ़ोन का इस्तेमाल करते हैं"</string>
@@ -1082,15 +1081,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> में बदलाव के लिए पुष्टि करें"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ज़्यादा देखने के लिए स्वाइप करें"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सुझाव लोड हो रहे हैं"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"इस मीडिया सेशन को छिपाएं."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"छिपाएं"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</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>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 262fef5b21a9..48be21a292ff 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -456,10 +456,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite opet za otvaranje"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Prijeđite prstom prema gore da biste otvorili"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Prijeđite prstom prema gore za ponovni pokušaj"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Prijeđite prstom od ikone za telefon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Prijeđite prstom od ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="4519495795000658637">"Prijeđite prstom od ikone za fotoaparat"</string>
@@ -526,33 +524,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil se možda nadzire"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Mreža se možda nadzire"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Mreža se možda nadzire"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša je organizacija vlasnik ovog uređaja i može nadzirati mrežni promet"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Organizacija <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> vlasnik je ovog uređaja i može nadzirati mrežni promet"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ovaj uređaj pripada vašoj organizaciji i povezan je s mrežom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je s mrežom <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Ovaj uređaj pripada vašoj organizaciji"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Ovaj uređaj pripada vašoj organizaciji i povezan je s VPN-ovima"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je s VPN-ovima"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Vaša organizacija može nadzirati mrežni promet na vašem radnom profilu"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Organizacija <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> može nadzirati mrežni promet na vašem radnom profilu"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Mreža se možda nadzire"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Ovaj je uređaj povezan s VPN-ovima"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Vaš poslovni profil povezan je s mrežom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Vaš osobni profil povezan je s mrežom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Ovaj uređaj povezan je s mrežom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Upravljanje uređajem"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Nadzor profila"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Nadzor mreže"</string>
@@ -562,10 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Onemogući VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini vezu s VPN-om"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži pravila"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVaš IT administrator može nadzirati postavke, korporacijski pristup, aplikacije, podatke o uređaju i lokaciji uređaja te upravljati njima.\n\nZa više informacija obratite se IT administratoru."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Ovaj uređaj pripada vašoj organizaciji.\n\nVaš IT administrator može nadzirati postavke, korporacijski pristup, aplikacije, podatke o uređaju i lokaciji uređaja te upravljati njima.\n\nZa više informacija obratite se IT administratoru."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Vaša je organizacija instalirala izdavač certifikata na ovom uređaju. Vaš sigurni mrežni promet možda se nadzire ili modificira."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Vaša je organizacija instalirala izdavač certifikata na vašem radnom profilu. Vaš sigurni mrežni promet možda se nadzire ili modificira."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Na ovom je uređaju instaliran izdavač certifikata. Vaš sigurni mrežni promet možda se nadzire ili modificira."</string>
@@ -941,8 +925,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pauziraj"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Preskoči na sljedeće"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Preskoči na prethodno"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Promjena veličine"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon se isključio zbog vrućine"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefon sada radi normalno"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon se pregrijao, stoga se isključio kako bi se ohladio Telefon sada radi normalno.\n\nTelefon se može pregrijati ako:\n • upotrebljavate zahtjevne aplikacije (kao što su igre, aplikacije za videozapise ili navigaciju)\n • preuzimate ili prenosite velike datoteke\n • upotrebljavate telefon na visokim temperaturama."</string>
@@ -1086,15 +1069,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdite promjenu za uređaj <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Prijeđite prstom da vidite više"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Sakrij trenutačnu sesiju."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Pogreška, pokušavamo ponovo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d78bdae3cf9c..b311c27a2daf 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Szüneteltetés"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Ugrás a következőre"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Ugrás az előzőre"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Átméretezés"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"A meleg miatt kikapcsolt"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"A telefon most már megfelelően működik"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonja túlmelegedett, így kikapcsolt, hogy lehűlhessen. Most már megfelelően működik.\n\nA telefon akkor melegedhet túl, ha Ön:\n • Energiaigényes alkalmazásokat használ (például játékokat, videókat vagy navigációs alkalmazásokat)\n • Nagy fájlokat tölt le vagy fel\n • Melegben használja a telefonját"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"A(z) <xliff:g id="DEVICE">%s</xliff:g> módosításának megerősítése"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Továbbiak megtekintéséhez csúsztasson"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Javaslatok betöltése…"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Jelenlegi munkamenet elrejtése."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Elrejtés"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hiba, újrapróbálkozás…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nem található"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 499f9734d297..cbc3268115fc 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Դադարեցնել"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Անցնել հաջորդին"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Վերադառնալ նախորդին"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Փոխել չափը"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Հեռախոսն անջատվել է տաքանալու պատճառով"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Հեռախոսն այժմ նորմալ աշխատում է"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Ձեր հեռախոսը չափազանց տաք էր, այդ պատճառով այն անջատվել է՝ հովանալու համար: Հեռախոսն այժմ նորմալ աշխատում է:\n\nՀեռախոսը կարող է տաքանալ, եթե՝\n • Օգտագործում եք ռեսուրսատար հավելվածներ (օրինակ՝ խաղեր, տեսանյութեր կամ նավարկման հավելվածներ)\n • Ներբեռնում կամ վերբեռնում եք ծանր ֆայլեր\n • Օգտագործում եք ձեր հեռախոսը բարձր ջերմային պայմաններում"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 426eed143fc4..4fa434488c55 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Jeda"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Lewati ke berikutnya"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Lewati ke sebelumnya"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Ubah ukuran"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Ponsel dimatikan karena panas"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Ponsel kini berfungsi normal"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Ponsel menjadi terlalu panas, jadi dimatikan untuk mendinginkan. Ponsel kini berfungsi normal.\n\nPonsel dapat menjadi terlalu panas jika Anda:\n • Menggunakan aplikasi yang menggunakan sumber daya secara intensif (seperti aplikasi game, video, atau navigasi)\n • Mendownload atau mengupload file besar\n • Menggunakan ponsel dalam suhu tinggi"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 3f93908b62d1..82ceb4e43aac 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Ýttu aftur til að opna"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Strjúktu upp til að opna"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Strjúktu upp til að reyna aftur"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Þetta tæki tilheyrir fyrirtækinu þínu"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Strjúktu frá tákninu fyrir síma"</string>
<string name="voice_hint" msgid="7476017460191291417">"Strjúktu frá tákninu fyrir raddaðstoð"</string>
<string name="camera_hint" msgid="4519495795000658637">"Strjúktu frá tákninu fyrir myndavél"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Hugsanlega er fylgst með þessu sniði"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Hugsanlega er fylgst með netinu"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Hugsanlega er fylgst með netinu"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Fyrirtækið þitt á þetta tæki og fylgist hugsanlega með netumferð"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> á þetta tæki og fylgist hugsanlega með netumferð"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Þetta tæki tilheyrir fyrirtækinu þínu og er tengt við <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og er tengt við <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Þetta tæki tilheyrir fyrirtækinu þínu"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Þetta tæki tilheyrir fyrirtækinu þínu og er tengt við VPN-net"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og er tengt við VPN-net"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Fyrirtækið þitt kann að fylgjast með netnotkun á vinnusniðinu þínu"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kann að fylgjast með netnotkun á vinnusniðinu þínu"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Hugsanlega er fylgst með netinu"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Þetta tæki er tengt við VPN-net"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Vinnusniðið þitt er tengt við <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Einkaprófíllinn þinn er tengdur við <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Þetta tæki er tengt við <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Tækjastjórnun"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Fylgst með sniði"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Neteftirlit"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Slökkva á VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Aftengja VPN-net"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Skoða stefnur"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nKerfisstjórinn getur fylgst með og breytt stillingum, fyrirtækjaaðgangi, forritum, gögnum sem tengjast tækinu þínu og staðsetningarupplýsingum tækisins.\n\nHafðu samband við kerfisstjórann til að fá frekari upplýsingar."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Þetta tæki tilheyrir fyrirtækinu þínu.\n\nKerfisstjórinn getur fylgst með og breytt stillingum, fyrirtækjaaðgangi, forritum, gögnum sem tengjast tækinu þínu og staðsetningarupplýsingum tækisins.\n\nHafðu samband við kerfisstjórann til að fá frekari upplýsingar."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Fyrirtækið þitt setti upp CA-vottorð á þessu tæki. Eftirlit kann að vera haft með öruggri netnotkun þinni eða henni kann að vera breytt."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Fyrirtækið þitt setti upp CA-vottorð á vinnusniðinu þínu. Eftirlit kann að vera haft með öruggri netnotkun þinni eða henni kann að vera breytt."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"CA-vottorð er uppsett á þessu tæki. Eftirlit kann að vera haft með öruggri netnotkun þinni eða henni kann að vera breytt."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Gera hlé"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Fara á næsta"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Fara á fyrra"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Breyta stærð"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Slökkt var á símanum vegna hita"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Síminn virkar núna sem skyldi"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Síminn varð of heitur og því var slökkt á honum til að kæla hann. Síminn virkar núna sem skyldi.\n\nSíminn getur orðið of heitur ef þú:\n • Notar plássfrek forrit (t.d. leikja-, myndbands- eða leiðsagnarforrit\n • Sækir eða hleður upp stórum skrám\n • Notar símann í miklum hita"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Staðfesta breytingu fyrir <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Strjúktu til að sjá meira"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Hleður tillögum"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Margmiðlunarefni"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Fela núverandi lotu."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fela"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Villa, reynir aftur…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Fannst ekki"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0b01f914b20f..6f6ca2b0a7fc 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Metti in pausa"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Passa ai contenuti successivi"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Passa ai contenuti precedenti"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Ridimensiona"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Il telefono si è spento perché surriscaldato"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Ora il telefono funziona normalmente"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Il telefono era surriscaldato e si è spento per raffreddarsi. Ora funziona normalmente.\n\nIl telefono può surriscaldarsi se:\n • Utilizzi app che consumano molte risorse (ad esempio app di navigazione, giochi o video)\n • Scarichi o carichi grandi file\n • Lo utilizzi in presenza di alte temperature"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Conferma modifica per <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Scorri per vedere altro"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Caricamento dei consigli"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Contenuti multimediali"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Nascondi la sessione attuale."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Nascondi"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Errore. Nuovo tentativo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Controllo non trovato"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index a622f5f956f6..b7a726e1fe1e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -946,8 +946,7 @@
<string name="pip_pause" msgid="1139598607050555845">"השהה"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"אפשר לדלג אל הבא"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"אפשר לדלג אל הקודם"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"שינוי גודל"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"הטלפון כבה עקב התחממות"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"הטלפון פועל כרגיל עכשיו"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"הטלפון שלך התחמם יותר מדי וכבה כדי להתקרר. הטלפון פועל כרגיל עכשיו.\n\nייתכן שהטלפון יתחמם יותר מדי אם:\n • תשתמש באפליקציות עתירות משאבים (כגון משחקים, אפליקציות וידאו או אפליקציות ניווט)\n • תוריד או תעלה קבצים גדולים\n • תשתמש בטלפון בטמפרטורות גבוהות"</string>
@@ -1092,15 +1091,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"יש לאשר את השינוי עבור <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"יש להחליק כדי להציג עוד פריטים"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"בטעינת המלצות"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"מדיה"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"הסתרת הסשן הנוכחי."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"הסתרה"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</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>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4f4ef02360f1..38904f594907 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"開くにはもう一度タップしてください"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"開くには上にスワイプします"</string>
<string name="keyguard_retry" msgid="886802522584053523">"上にスワイプしてもう一度お試しください"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"これは組織が所有するデバイスです"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"これは <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> が所有するデバイスです"</string>
<string name="phone_hint" msgid="6682125338461375925">"右にスワイプして通話"</string>
<string name="voice_hint" msgid="7476017460191291417">"アイコンからスワイプして音声アシストを起動"</string>
<string name="camera_hint" msgid="4519495795000658637">"左にスワイプしてカメラを起動"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"プロファイルが監視されている可能性があります"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ネットワークが監視されている可能性があります"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ネットワークが監視されている可能性があります"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"これは組織が所有するデバイスで、ネットワーク トラフィックが監視されることもあります"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"これは <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> が所有するデバイスで、ネットワーク トラフィックが監視されることもあります"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"これは組織が所有するデバイスで、<xliff:g id="VPN_APP">%1$s</xliff:g> に接続しています"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"これは <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> が所有するデバイスで、<xliff:g id="VPN_APP">%2$s</xliff:g> に接続しています"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"これは組織が所有するデバイスです"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"これは <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> が所有するデバイスです"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"これは組織が所有するデバイスで、VPN に接続しています"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"これは <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> が所有するデバイスで、VPN に接続しています"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"組織は仕事用プロファイルのネットワーク トラフィックを監視することがあります"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> によってこの仕事用プロファイルのネットワーク トラフィックが監視されることもあります"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ネットワークが監視されることもあります"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"このデバイスは VPN に接続しています"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"この仕事用プロファイルは <xliff:g id="VPN_APP">%1$s</xliff:g> に接続しています"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"この個人用プロファイルは <xliff:g id="VPN_APP">%1$s</xliff:g> に接続しています"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"このデバイスは <xliff:g id="VPN_APP">%1$s</xliff:g> に接続しています"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"デバイス管理"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"プロファイルの監視"</string>
<string name="monitoring_title" msgid="4063890083735924568">"ネットワーク監視"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPNを無効にする"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPNを切断"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ポリシーを見る"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"これは <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> が所有するデバイスです。\n\nIT 管理者が、このデバイスに関連付けられている設定、コーポレート アクセス、アプリ、データのほか、デバイスの位置情報を監視、管理できます。\n\n詳しくは、IT 管理者にお問い合わせください。"</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"これは組織が所有するデバイスです。\n\nIT 管理者が、このデバイスに関連付けられている設定、コーポレート アクセス、アプリ、データのほか、デバイスの位置情報を監視、管理できます。\n\n詳しくは、IT 管理者にお問い合わせください。"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"組織によってこのデバイスに認証局がインストールされました。保護されたネットワーク トラフィックが監視、変更される場合があります。"</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"組織によって、あなたの仕事用プロファイルに認証局がインストールされました。保護されたネットワーク トラフィックが監視、変更される場合があります。"</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"このデバイスには認証局がインストールされています。保護されたネットワーク トラフィックが監視、変更される可能性があります。"</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"一時停止"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"次へスキップ"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"前へスキップ"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"サイズ変更"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"高熱で電源が OFF になりました"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"お使いのスマートフォンは現在、正常に動作しています"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"スマートフォンが熱すぎたため電源が OFF になりました。現在は正常に動作しています。\n\nスマートフォンは以下の場合に熱くなる場合があります。\n • リソースを集中的に使用する機能やアプリ(ゲームアプリ、動画アプリ、ナビアプリなど)を使用\n • サイズの大きいファイルをダウンロードまたはアップロード\n • 高温の場所で使用"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>の変更を確認する"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"スワイプすると他の構造が表示されます"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"候補を読み込んでいます"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"メディア"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"現在のセッションを非表示にします。"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"非表示"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"再開"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</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>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 29e740ef0e57..72a494a9f7c7 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"შეეხეთ ისევ გასახსნელად"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"გასახსნელად გადაფურცლეთ ზემოთ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ხელახლა საცდელად გადაფურცლეთ ზემოთ"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"ტელეფონისთვის გადაფურცლეთ ხატულადან"</string>
<string name="voice_hint" msgid="7476017460191291417">"ხმოვანი დახმარებისთვის გადაფურცლეთ ხატულადან"</string>
<string name="camera_hint" msgid="4519495795000658637">"კამერისთვის გადაფურცლეთ ხატულადან"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"შესაძლოა პროფილზე ხორციელდებოდეს მონიტორინგი"</string>
<string name="vpn_footer" msgid="3457155078010607471">"შესაძლოა ქსელზე ხორციელდება მონიტორინგი"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ქსელზე შესაძლოა მონიტორინგი ხორციელდებოდეს"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია და მას ქსელის ტრაფიკის მონიტორინგი შეუძლია"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> და მას ქსელის ტრაფიკის მონიტორინგი შეუძლია"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია და ის დაკავშირებულია <xliff:g id="VPN_APP">%1$s</xliff:g>-თან"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> და ის დაკავშირებულია <xliff:g id="VPN_APP">%2$s</xliff:g>-თან"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია და ის დაკავშირებულია VPN-ებთან"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> და ის დაკავშირებულია VPN-ებთან"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"თქვენს ორგანიზაციას სამსახურის პროფილში ქსელის ტრაფიკის მონიტორინგი შეუძლია"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>-ს სამსახურის პროფილში ქსელის ტრაფიკის მონიტორინგი შეუძლია"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ქსელზე შესაძლოა ხორციელდებოდეს მონიტორინგი"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"ეს მოწყობილობა დაკავშირებულია VPN-ებთან"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"თქვენი სამსახურის პროფილი დაკაცშირებულია <xliff:g id="VPN_APP">%1$s</xliff:g>-თან"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"თქვენი პერსონალური პროფილი დაკავშირებულია <xliff:g id="VPN_APP">%1$s</xliff:g>-თან"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"ეს მოწყობილობა დაკავშირებულია <xliff:g id="VPN_APP">%1$s</xliff:g>-თან"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"მოწყობილობის მართვა"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"პროფილის მონიტორინგი"</string>
<string name="monitoring_title" msgid="4063890083735924568">"ქსელის მონიტორინგი"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN-ის გაუქმება"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN-ის გათიშვა"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"წესების ნახვა"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"ეს მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nთქვენს IT ადმინისტრატორს შეუძლია მოწყობილობასთან დაკავშირებული პარამეტრების, კორპორაციული წვდომის, აპებისა და მონაცემების (მათ შორის, თქვენი მოწყობილობის მდებარეობის ინფორმაციის) მონიტორინგი და მართვა.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს IT ადმინისტრატორს."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია.\n\nთქვენს IT ადმინისტრატორს შეუძლია მოწყობილობასთან დაკავშირებული პარამეტრების, კორპორაციული წვდომის, აპებისა და მონაცემების (მათ შორის, თქვენი მოწყობილობის მდებარეობის ინფორმაციის) მონიტორინგი და მართვა.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს IT ადმინისტრატორს."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"თქვენმა ორგანიზაციამ ამ მოწყობილობაზე სერტიფიცირების ორგანო დააინსტალირა. თქვენი ქსელის დაცული ტრაფიკი შეიძლება შეიცვალოს, ან მასზე მონიტორინგი განხორციელდეს."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"თქვენმა ორგანიზაციამ სამსახურის პროფილში სერტიფიცირების ორგანო დააინსტალირა. თქვენი ქსელის დაცული ტრაფიკი შეიძლება შეიცვალოს, ან მასზე მონიტორინგი განხორციელდეს."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ამ მოწყობილობაზე დაინსტალირებულია სერტიფიცირების ორგანო. თქვენი ქსელის დაცული ტრაფიკი შეიძლება შეიცვალოს, ან მასზე მონიტორინგი განხორციელდეს."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"დაპაუზება"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"შემდეგზე გადასვლა"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"წინაზე გადასვლა"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"ზომის შეცვლა"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"ტელეფონი გამოირთო გაცხელების გამო"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"თქვენი ტელეფონი ახლა ჩვეულებრივად მუშაობს"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"თქვენი ტელეფონი გამოირთო გასაგრილებლად, რადგან ის მეტისმეტად გაცხელდა. ახლა ის ჩვეულებრივად მუშაობს.\n\nტელეფონის გაცხელების მიზეზებია:\n • რესურსტევადი აპების გამოყენება (მაგ. სათამაშო, ვიდეო ან ნავიგაციის აპების)\n • დიდი ფაილების ჩამოტვირთვა ან ატვირთვა\n • ტელეფონის გამოყენება მაღალი ტემპერატურისას"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"დაადასტურეთ ცვლილება <xliff:g id="DEVICE">%s</xliff:g>-ისთვის"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"გადაფურცლეთ მეტის სანახავად"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"მიმდინარეობს რეკომენდაციების ჩატვირთვა"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"მედია"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"დაიმალოს მიმდინარე სესია"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"დამალვა"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"გაგრძელება"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"პარამეტრები"</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>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index d3d3996c290a..83e18419151d 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Кідірту"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Келесіге өту"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Алдыңғысына оралу"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Өлшемін өзгерту"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Телефон қызып кеткендіктен өшірілді"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Телефоныңыз қазір қалыпты жұмыс істеп тұр"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Телефоныңыз қатты қызып кеткендіктен өшірілді. Телефоныңыз қазір қалыпты жұмыс істеп тұр.\n\nТелефоныңыз мына жағдайларда ыстық болуы мүмкін:\n • Ресурстар талап ететін қолданбаларды пайдалану (ойын, бейне немесе навигация қолданбалары)\n • Үлкен көлемді файлдарды жүктеу немесе жүктеп салу\n • Телефонды жоғары температурада пайдалану"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 02d571076c57..bc30c41641c0 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"ផ្អាក"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"រំលងទៅបន្ទាប់"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"រំលងទៅក្រោយ"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"ប្ដូរ​ទំហំ"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"ទូរសព្ទ​បាន​បិទដោយសារ​វា​ឡើងកម្តៅ"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"ឥឡូវនេះ​ទូរសព្ទ​របស់អ្នក​កំពុង​ដំណើរការ​ធម្មតា"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"ទូរសព្ទ​របស់អ្នក​ក្តៅពេក ដូច្នេះ​វាបាន​បិទ​ដើម្បី​បន្ថយ​កម្តៅ។ ឥឡូវនេះ ​ទូរសព្ទ​របស់អ្នក​កំពុង​ដំណើរការ​ធម្មតា។\n\nទូរសព្ទ​របស់អ្នក​អាចនឹង​ឡើង​កម្តៅ​ខ្លាំងជ្រុល ប្រសិន​បើអ្នក៖\n • ប្រើប្រាស់​កម្មវិធី​ដែល​ប្រើប្រាស់ទិន្នន័យច្រើនក្នុងរយៈពេលខ្លី (ដូចជាហ្គេម វីដេអូ ឬកម្មវិធីរុករក)\n • ទាញយក ឬ​បង្ហោះ​ឯកសារដែលមានទំហំធំ\n • ប្រើប្រាស់​ទូរសព្ទ​របស់អ្នក​នៅកន្លែង​មានសីតុណ្ហភាព​ខ្ពស់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index f9e9ace79f99..73461f31efa9 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ತೆರೆಯಲು ಮತ್ತೆ ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ತೆರೆಯಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ಗೆ ಸೇರಿದೆ"</string>
<string name="phone_hint" msgid="6682125338461375925">"ಫೋನ್‌ಗಾಗಿ ಐಕಾನ್‌ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="voice_hint" msgid="7476017460191291417">"ಧ್ವನಿ ಸಹಾಯಕ್ಕಾಗಿ ಐಕಾನ್‌ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="camera_hint" msgid="4519495795000658637">"ಕ್ಯಾಮರಾಗಾಗಿ ಐಕಾನ್‌ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ಪ್ರೊಫೈಲ್ ಅನ್ನು ಪರಿವೀಕ್ಷಿಸಬಹುದಾಗಿದೆ"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ನೆಟ್‌ವರ್ಕ್ ಅನ್ನು ವೀಕ್ಷಿಸಬಹುದಾಗಿ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ನೆಟ್‌ವರ್ಕ್ ಅನ್ನು ವೀಕ್ಷಿಸಬಹುದಾಗಿರುತ್ತದೆ"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನದ ಮಾಲೀಕತ್ವವನ್ನು ಹೊಂದಿದೆ ಮತ್ತು ಅದು ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್‌ನ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಈ ಸಾಧನದ ಮಾಲೀಕತ್ವವನ್ನು ಹೊಂದಿದೆ ಮತ್ತು ಅದು ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್‌ನ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ ಮತ್ತು <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಗೆ ಸೇರಿದೆ ಮತ್ತು <xliff:g id="VPN_APP">%2$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಗೆ ಸೇರಿದೆ"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ ಮತ್ತು VPN ಗಳಿಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಗೆ ಸೇರಿದೆ ಮತ್ತು VPN ಗಳಿಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ನೆಟ್‌ವರ್ಕ್‌ನ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾಗಿದೆ"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"ಈ ಸಾಧನವು VPN ಗಳಿಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್ <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"ಈ ಸಾಧನವು <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"ಸಾಧನ ನಿರ್ವಹಣೆ"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"ಪ್ರೊಫೈಲ್ ಮೇಲ್ವಿಚಾರಣೆ"</string>
<string name="monitoring_title" msgid="4063890083735924568">"ನೆಟ್‌ವರ್ಕ್‌ ಪರಿವೀಕ್ಷಣೆ"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ಸಂಪರ್ಕಕಡಿತಗೊಳಿಸಿ"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ಕಾರ್ಯನೀತಿಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಗೆ ಸೇರಿದೆ.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳು, ಕಾರ್ಪೊರೇಟ್ ಪ್ರವೇಶ, ಆ್ಯಪ್‌ಗಳು, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳದ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳು, ಕಾರ್ಪೊರೇಟ್ ಪ್ರವೇಶ, ಆ್ಯಪ್‌ಗಳು, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳದ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನದಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ಈ ಸಾಧನದಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
@@ -1079,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ಸಾಧನಕ್ಕಾಗಿ ಬದಲಾವಣೆಯನ್ನು ದೃಢೀಕರಿಸಿ"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ಇನ್ನಷ್ಟು ನೋಡಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"ಮಾಧ್ಯಮ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"ಪ್ರಸ್ತುತ ಸೆಶನ್ ಅನ್ನು ಮರೆಮಾಡಿ."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ಮರೆಮಾಡಿ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 04da96b8750b..23831b1f21de 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"일시중지"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"다음으로 건너뛰기"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"이전으로 건너뛰기"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"크기 조절"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"발열로 인해 휴대전화 전원이 종료됨"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"휴대전화가 정상적으로 실행 중입니다."</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"휴대전화가 과열되어 온도를 낮추기 위해 전원이 종료되었습니다. 지금은 휴대전화가 정상적으로 실행 중입니다.\n\n휴대전화가 과열되는 이유는 다음과 같습니다.\n • 리소스를 많이 사용하는 앱 사용(예: 게임, 동영상 또는 내비게이션 앱)\n • 대용량 파일을 다운로드 또는 업로드\n • 온도가 높은 곳에서 휴대폰 사용"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 424d3c818b35..5fc2b7d280b2 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Тындыруу"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Кийинкисине өткөрүп жиберүү"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Мурункусуна өткөрүп жиберүү"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Өлчөмүн өзгөртүү"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Телефон ысыгандыктан өчүрүлдү"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Телефонуңуз кадимкидей иштеп жатат"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Телефонуңуз өтө ысып кеткендиктен, аны муздатуу үчүн өчүрүлдү. Эми телефонуңуз кадимкидей иштеп жатат.\n\nТелефонуңуз төмөнкү шарттарда ысып кетиши мүмкүн:\n • Ашыкча ресурс короткон колдонмолорду (оюндар, видео же чабыттоо колдонмолору) пайдалансаңыз \n • Ири көлөмдөгү файлдарды жүктөп алсаңыз же берсеңиз\n • Телефонуңузду жогорку температураларда пайдалансаңыз"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 861af7daafb2..1f5254616413 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ແຕະ​ອີກ​ຄັ້ງ​ເພື່ອ​ເປີດ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ປັດຂຶ້ນເພື່ອເປີດ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ປັດຂຶ້ນເພື່ອລອງໃໝ່"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"ອຸ​ປະ​ກອນ​ນີ້​ເປັນ​ຂອງ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"ປັດ​ຈາກ​ໄອ​ຄອນ​ສຳ​ລັບ​ໂທ​ລະ​ສັບ"</string>
<string name="voice_hint" msgid="7476017460191291417">"ປັດ​ຈາກ​ໄອ​ຄອນ​ສຳ​ລັບ​ການ​ຊ່ວຍ​ທາງ​ສຽງ"</string>
<string name="camera_hint" msgid="4519495795000658637">"ປັດ​ຈາກ​ໄອ​ຄອນ​ສຳ​ລັບ​ກ້ອງ​ຖ່າຍ​ຮູບ"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ໂປຣ​ໄຟລ໌​ອາດ​ຖືກ​ເຝົ້າ​ຕິດ​ຕາມ​ຢູ່"</string>
<string name="vpn_footer" msgid="3457155078010607471">"​ເຄືອ​ຂ່າຍ​ອາດ​ມີ​ການ​ເຝົ້າ​ຕິດ​ຕາມ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ການນຳໃຊ້ເຄືອຂ່າຍອາດມີການກວດສອບຕິດຕາມ"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ອົງການຂອງທ່ານເປັນເຈົ້າຂອງອຸປະກອນນີ້ ແລະ ສາມາດຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໄດ້"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ເປັນເຈົ້າຂອງອຸປະກອນນີ້ ແລະ ສາມາດຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໄດ້"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ ແລະ ເຊື່ອມຕໍ່ຫາ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"ອຸປະກອນນີ້ເປັນຂອງ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ແລະ ເຊື່ອມຕໍ່ຫາ <xliff:g id="VPN_APP">%2$s</xliff:g> ແລ້ວ"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"ອຸ​ປະ​ກອນ​ນີ້​ເປັນ​ຂອງ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ ແລະ ເຊື່ອມຕໍ່ຫາ VPN ແລ້ວ"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"ອຸປະກອນນີ້ເປັນຂອງ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ແລະ ເຊື່ອມຕໍ່ຫາ VPN ແລ້ວ"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"ອົງກອນຂອງທ່ານສາມາດຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໃນໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານໄດ້"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ສາມາດຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໃນໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານໄດ້"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ເຄືອຂ່າຍອາດຖືກຕິດຕາມ"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"ໂປຣໄຟລ໌ສ່ວນຕົວຂອງທ່ານເຊື່ອມຕໍ່ຫາ VPN ແລ້ວ"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານເຊື່ອມຕໍ່ຫາ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"ໂປຣໄຟລ໌ສ່ວນຕົວຂອງທ່ານເຊື່ອມຕໍ່ຫາ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"ອຸປະກອນນີ້ເຊື່ອມຕໍ່ຫາ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"ການຈັດການອຸປະກອນ"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"ການ​ຕິດ​ຕາມ​ໂປຣ​ໄຟລ໌"</string>
<string name="monitoring_title" msgid="4063890083735924568">"ການກວດ​ສອບ​ຕິດ​ຕາມ​ເຄືອ​ຂ່າຍ"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"ປິດ​ການ​ໃຊ້ VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"ຕັດ​ການ​ເຊື່ອມ​ຕໍ່ VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ເບິ່ງນະໂຍບາຍ"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"ອຸປະກອນນີ້ເປັນຂອງ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານສາມາດເຝົ້າຕິດຕາມ ແລະ ຈັດການການຕັ້ງຄ່າ, ສິດເຂົ້າເຖິງອົງກອນ, ແອັບ, ຂໍ້ມູນທີ່ເຊື່ອມໂຍງກັບອຸປະກອນຂອງທ່ານໄດ້.\n\nສຳລັບຂໍ້ມູນເພີ່ມເຕີມ, ກະລຸນາຕິດຕໍ່ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານ."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ.\n\nຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານສາມາດເຝົ້າຕິດຕາມ ແລະ ຈັດການການຕັ້ງຄ່າ, ສິດເຂົ້າເຖິງອົງກອນ, ແອັບ, ຂໍ້ມູນທີ່ເຊື່ອມໂຍງກັບອຸປະກອນຂອງທ່ານໄດ້.\n\nສຳລັບຂໍ້ມູນເພີ່ມເຕີມ, ກະລຸນາຕິດຕໍ່ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານ."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ອົງກອນຂອງທ່ານຕິດຕັ້ງອຳນາດໃບຮັບຮອງໄວ້ໃນອຸປະກອນນີ້. ທຣາບຟິກເຄືອຂ່າຍທີ່ເຂົ້າລະຫັດໄວ້ຂອງທ່ານອາດຖືກຕິດຕາມ ຫຼື ແກ້ໄຂໄດ້."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ອົງກອນຂອງທ່ານຕິດຕັ້ງອຳນາດໃບຮັບຮອງໄວ້ໃນໂປຣໄຟລ໌ບ່ອນເຮັດວຽກນີ້. ທຣາບຟິກເຄືອຂ່າຍທີ່ເຂົ້າລະຫັດໄວ້ຂອງທ່ານອາດຖືກຕິດຕາມ ຫຼື ແກ້ໄຂໄດ້."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ມີອຳນາດໃບຮັບຮອງຕິດຕັ້ງຢູ່ໃນອຸປະກອນນີ້. ທຣາບຟິກເຄືອຂ່າຍທີ່ເຂົ້າລະຫັດໄວ້ຂອງທ່ານອາດຖືກຕິດຕາມ ຫຼື ແກ້ໄຂໄດ້."</string>
@@ -1079,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"ຢືນຢັນການປ່ຽນແປງສຳລັບ <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ປັດເພື່ອເບິ່ງເພີ່ມເຕີມ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"ມີເດຍ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"ເຊື່ອງເຊດຊັນປັດຈຸບັນ."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ເຊື່ອງ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</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>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 7a92c1a73f91..ed02b486efbf 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -946,8 +946,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pristabdyti"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Praleisti ir eiti į kitą"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Praleisti ir eiti į ankstesnį"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Pakeisti dydį"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefonas išjungt., nes įkaito"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Dabar telefonas veikia įprastai"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonas per daug įkaito, todėl buvo išj., kad atvėstų. Dabar telefonas veikia įprastai.\n\nTelefonas gali per daug įkaisti, jei:\n • esate įjungę daug išteklių naudoj. progr. (pvz., žaidimų, vaizdo įr. arba navig. progr.);\n • atsis. arba įkeliate didelius failus;\n • telefoną naudojate aukštoje temper."</string>
@@ -1092,15 +1091,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Patvirtinti <xliff:g id="DEVICE">%s</xliff:g> pakeitimą"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Perbraukite, kad peržiūrėtumėte daugiau"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Įkeliamos rekomendacijos"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Medija"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Slėpti dabartinį seansą."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Slėpti"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Tęsti"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Nustatymai"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Klaida, bandoma iš naujo…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nerasta"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 3c95ad6b726c..09b0fc3d3ce7 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -941,8 +941,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Apturēt"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Pāriet uz nākamo"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Pāriet uz iepriekšējo"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Mainīt lielumu"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Tālrunis izslēgts karstuma dēļ"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Tagad jūsu tālrunis darbojas normāli"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Jūsu tālrunis bija pārkarsis un tika izslēgts. Tagad tas darbojas normāli.\n\nTālrunis var sakarst, ja:\n • tiek izmantotas lietotnes, kas patērē daudz enerģijas (piem., spēles, video lietotnes vai navigācija);\n • tiek lejupielādēti/augšupielādēti lieli faili;\n • tālrunis tiek lietots augstā temperatūrā."</string>
@@ -1086,15 +1085,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Izmaiņu apstiprināšana ierīcei <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Velciet, lai skatītu citus vienumus"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Notiek ieteikumu ielāde"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Multivide"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Paslēpiet pašreizējo sesiju."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Paslēpt"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Atsākt"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Iestatījumi"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Radās kļūda. Mēģina vēlreiz…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Netika atrasta"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 72370a241318..1dbae2790e56 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Допрете повторно за да се отвори"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Повлечете за да отворите"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Повлечете нагоре за да се обидете повторно"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Уредов е во сопственост на организацијата"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Повлечете од иконата за телефонот"</string>
<string name="voice_hint" msgid="7476017460191291417">"Повлечете од иконата за гласовна помош"</string>
<string name="camera_hint" msgid="4519495795000658637">"Повлечете од иконата за камерата"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профилот можеби се следи"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Мрежата може да се следи"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Мрежата може да се следи"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организацијата управува со уредов и може да го следи мрежниот сообраќај"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> е сопственик на уредов и може да го следи мрежниот сообраќај"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Уредов е во сопственост на организацијата и е поврзан со <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> и е поврзан со <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Уредов е во сопственост на организацијата"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Уредов е во сопственост на организацијата и е поврзан со VPN-мрежи"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> и е поврзан со VPN-мрежи"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Вашата организација може да го следи мрежниот сообраќај на вашиот работен профил"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> може да го следи мрежниот сообраќај на вашиот работен профил"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Мрежата можеби се следи"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Уредов е поврзан со VPN-мрежи"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Вашиот работен профил е поврзан со <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Вашиот личен профил е поврзан со <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Уредов е поврзан со <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Управување со уреди"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Следење профил"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Следење на мрежата"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Оневозможи ВПН"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Исклучи ВПН"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Прикажи „Политики“"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT-администраторот може да ги следи и да управува со поставките, корпоративниот пристап, апликациите, податоците поврзани со уредот и информациите за локацијата на уредот.\n\nЗа повеќе информации, контактирајте со IT-администраторот."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Уредов е во сопственост на организацијата.\n\nIT-администраторот може да ги следи и да управува со поставките, корпоративниот пристап, апликациите, податоците поврзани со уредот и информациите за локацијата на уредот.\n\nЗа повеќе информации, контактирајте со IT-администраторот."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Вашата организација инсталираше авторитет за сертификат на уредов. Сообраќајот на вашата безбедна мрежа можно е да се следи или изменува."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Вашата организација инсталираше авторитет за сертификат на вашиот работен профил. Вашиот безбеден мрежен сообраќај можно е да се следи или изменува."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На уредов е инсталиран авторитет за сертификат. Вашиот безбеден мрежен сообраќај можно е да се следи или изменува."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Паузирај"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Прескокни до следната"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Прескокни до претходната"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Промени големина"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Телефонот се исклучи поради загреаност"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Сега телефонот работи нормално"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Телефонот беше премногу загреан, така што се исклучи за да се олади. Сега работи нормално.\n\nТелефонот може премногу да се загрее ако:\n • користите апликации што работат со многу ресурси (како што се, на пример, апликациите за видеа, навигација или игри)\n • преземате или поставувате големи датотеки\n •го користите телефонот на високи температури"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Потврдете ја промената за <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Повлечете за да видите повеќе"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Се вчитуваат препораки"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Аудиовизуелни содржини"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Сокриј ја тековнава сесија."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сокриј"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Продолжи"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Поставки"</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>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index ed22142c2dcc..bbc0d0692acb 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> എന്നതിനുള്ള മാറ്റം സ്ഥിരീകരിക്കുക"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"കൂടുതൽ കാണാൻ സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"നിർദ്ദേശങ്ങൾ ലോഡ് ചെയ്യുന്നു"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"മീഡിയ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"നിലവിലെ സെഷൻ മറയ്‌ക്കുക."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"മറയ്‌ക്കുക"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"പുനരാരംഭിക്കുക"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ക്രമീകരണം"</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>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index ee558511f81e..ca98a7c692ce 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Түр зогсоох"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Дараагийн медиад очих"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Өмнөх медиад очих"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Хэмжээг өөрчлөх"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Халснаас үүдэн утас унтарсан"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Таны утас одоо хэвийн ажиллаж байна"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Таны утас хэт халсан тул хөргөхөөр унтраасан болно. Таны утас одоо хэвийн ажиллаж байна.\n\nХэрэв та дараахыг хийвэл таны утас хэт халж болзошгүй:\n • Их хэмжээний нөөц хэрэглээний апп (тоглоом, видео эсвэл шилжилтийн апп зэрэг)\n • Багтаамж ихтэй файл татах, байршуулах\n • Утсаа өндөр температурт ашиглах"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 201f7e3ba781..1e043bbe666c 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> च्या बदलांची निश्चिती करा"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"अधिक पाहण्यासाठी स्वाइप करा"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"शिफारशी लोड करत आहे"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"सध्याचे सेशन लपवा."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लपवा"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"पुन्हा सुरू करा"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग्ज"</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>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 896f85a6807f..ca3515c9411d 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Jeda"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Langkau ke seterusnya"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Langkau ke sebelumnya"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Ubah saiz"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon dimatikan kerana panas"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefon anda kini berjalan seperti biasa"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon anda terlalu panas, jadi telefon itu telah dimatikan untuk menyejuk. Sekarang, telefon anda berjalan seperti biasa.\n\nTelefon anda mungkin menjadi terlalu panas jika anda:\n • Menggunakan apl intensif sumber (seperti permainan, video atau apl navigasi)\n • Memuat turun atau memuat naik fail besar\n • Menggunakan telefon anda dalam suhu tinggi"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 851505ffef38..29679d6a5650 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ဖွင့်ရန် ထပ်ပြီး ပုတ်ပါ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ဖွင့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ထပ်စမ်းကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> က ပိုင်ဆိုင်သည်"</string>
<string name="phone_hint" msgid="6682125338461375925">"ဖုန်းအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
<string name="voice_hint" msgid="7476017460191291417">"အသံအကူအညီအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
<string name="camera_hint" msgid="4519495795000658637">"ကင်မရာအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ပရိုဖိုင်ကို စောင့်ကြပ်နိုင်သည်"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ကွန်ရက်ကို ကို စောင့်ကြပ် နိုင်ပါသည်"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ကွန်ရက်ကို စောင့်ကြည့်စစ်ဆေးမှု ရှိနိုင်ပါသည်"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ဤစက်ကို သင့်အဖွဲ့အစည်းကပိုင်ဆိုင်ပြီး ကွန်ရက်ဒေတာ စီးဆင်းမှုကို စောင့်ကြည့်နိုင်ပါသည်"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> က ပိုင်ဆိုင်ပြီး ကွန်ရက်ဒေတာ စီးဆင်းမှုကို စောင့်ကြည့်နိုင်ပါသည်"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ဤစက်ကို သင့်အဖွဲ့အစည်းကပိုင်ဆိုင်ပြီး <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> က ပိုင်ဆိုင်ပြီး <xliff:g id="VPN_APP">%2$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> က ပိုင်ဆိုင်သည်"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"ဤစက်ကို သင့်အဖွဲ့အစည်းကပိုင်ဆိုင်ပြီး VPN များသို့ ချိတ်ဆက်ထားပါသည်"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> က ပိုင်ဆိုင်ပြီး VPN များသို့ ချိတ်ဆက်ထားပါသည်"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"သင်၏ အဖွဲ့အစည်းက သင့်အလုပ်ပရိုဖိုင်ရှိ ကွန်ရက်ဒေတာ စီးဆင်းမှုကို စောင့်ကြည့်နိုင်သည်"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> သည် သင်၏ အလုပ်ပရိုဖိုင်ရှိ ကွန်ရက်ဒေတာ စီးဆင်းမှုကို စောင့်ကြည့်နိုင်ပါသည်"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ကွန်ရက်ကို စောင့်ကြည့်နိုင်ပါသည်"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"ဤစက်ကို VPN များသို့ ချိတ်ဆက်ထားပါသည်"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"သင်၏အလုပ်ပရိုဖိုင်သည် <xliff:g id="VPN_APP">%1$s</xliff:g> ကို ချိတ်ဆက်ထားပါသည်"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"သင်၏ ကိုယ်ပိုင်ပရိုဖိုင်ကို <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"ဤစက်ကို <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"စက်ပစ္စည်း စီမံခန့်ခွဲမှု"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"ပရိုဖိုင် စောင့်ကြပ်မှု"</string>
<string name="monitoring_title" msgid="4063890083735924568">"ကွန်ရက်ကို စောင့်ကြပ်ခြင်း"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN ကို ပိတ်ထားရန်"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ကို အဆက်ဖြတ်ရန်"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"မူဝါဒများကို ကြည့်ရန်"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> က ပိုင်ဆိုင်ပါသည်။\n\nဆက်တင်များ၊ ကော်ပိုရိတ် သုံးခွင့်၊ အက်ပ်များ၊ သင့်စက်နှင့် ဆက်စပ်နေသော ဒေတာများနှင့် သင့်စက်တည်နေရာတို့ကို သင်၏ IT စီမံခန့်ခွဲသူက စောင့်ကြည့် စီမံနိုင်သည်။\n\nနောက်ထပ်အချက်အလက်များအတွက် သင်၏ IT စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်။\n\nဆက်တင်များ၊ ကော်ပိုရိတ် သုံးခွင့်၊ အက်ပ်များ၊ သင့်စက်နှင့် ဆက်စပ်နေသော ဒေတာများနှင့် သင့်စက်တည်နေရာတို့ကို သင်၏ IT စီမံခန့်ခွဲသူက စောင့်ကြည့် စီမံနိုင်သည်။\n\nနောက်ထပ်အချက်အလက်များအတွက် သင်၏ IT စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"သင်၏ အဖွဲ့အစည်းက ဤစက်ပစ္စည်းတွင် စီမံခန့်ခွဲမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ်ကို ထည့်သွင်းထားပါသည်။ လုံခြုံမှုရှိသော ကွန်ရက်ဒေတာစီးဆင်းမှုကို စောင့်ကြည့်ခြင်း သို့မဟုတ် ပြုပြင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်။"</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"သင်၏ အဖွဲ့အစည်းသည် သင်၏ အလုပ်ပရိုဖိုင်တွင် စီမံခန့်ခွဲမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ်ကို ထည့်သွင်းထားပါသည်။ လုံခြုံမှုရှိသော ကွန်ရက်ဒေတာစီးဆင်းမှုကို စောင့်ကြည့်ခြင်း သို့မဟုတ် ပြုပြင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်။"</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ဤစက်ပစ္စည်းတွင် စီမံခန့်ခွဲမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ်ကို ထည့်သွင်းထားပါသည်။ လုံခြုံမှုရှိသော ကွန်ရက်ဒေတာစီးဆင်းမှုကို စောင့်ကြည့်ခြင်း သို့မဟုတ် ပြုပြင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်။"</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"ခေတ္တရပ်ရန်"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"နောက်တစ်ခုသို့ ကျော်ရန်"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"ယခင်တစ်ခုသို့ ပြန်သွားရန်"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"အရွယ်အစားပြောင်းရန်"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"အပူရှိန်ကြောင့်ဖုန်းပိတ်ထားသည်"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"သင်၏ဖုန်းသည် ပုံမှန် အလုပ်လုပ်နေပါသည်"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"သင့်ဖုန်းအလွန်ပူနေသည့်အတွက် အေးသွားစေရန် ပိတ်ထားပါသည်။ ယခုပုံမှန် အလုပ်လုပ်ပါပြီ။\n\nအောက်ပါတို့ကိုသုံးလျှင် ပူလာပါမည်-\n • အရင်းအမြစ်များသောအက်ပ်ကို သုံးခြင်း (ဥပမာ ဂိမ်းကစားခြင်း၊ ဗီဒီယိုကြည့်ခြင်း (သို့) လမ်းညွှန်အက်ပ်)\n • ကြီးမားသောဖိုင်များ ဒေါင်းလုဒ် (သို့) အပ်လုဒ်လုပ်ခြင်း\n • အပူရှိန်မြင့်သောနေရာတွင် သုံးခြင်း"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> အတွက် အပြောင်းအလဲကို အတည်ပြုပါ"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ပိုမိုကြည့်ရှုရန် ပွတ်ဆွဲပါ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"အကြံပြုချက်များ ဖွင့်နေသည်"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"မီဒီယာ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"လက်ရှိ စက်ရှင်ကို ဖျောက်ထားမည်။"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ဖျောက်ထားမည်"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ဆက်လုပ်ရန်"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ဆက်တင်များ"</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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 6096cb1d6d24..1cb6067a704f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Trykk på nytt for å åpne"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Sveip opp for å åpne"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Sveip opp for å prøve igjen"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enheten tilhører organisasjonen din"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Sveip ikonet for å åpne telefon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Sveip fra ikonet for å åpne talehjelp"</string>
<string name="camera_hint" msgid="4519495795000658637">"Sveip ikonet for å åpne kamera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilen kan overvåkes"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Nettverket kan være overvåket"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Nettverket kan bli overvåket"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisasjonen din eier denne enheten og kan overvåke nettverkstrafikken"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> eier denne enheten og kan overvåke nettverkstrafikken"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Denne enheten tilhører organisasjonen din og er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og er koblet til <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Denne enheten tilhører organisasjonen din"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Denne enheten tilhører organisasjonen din og er koblet til VPN-er"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og er koblet til VPN-er"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Organisasjonen din kan overvåke nettverkstrafikken i jobbprofilen din"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kan overvåke nettverkstrafikken i jobbprofilen din"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Nettverket kan bli overvåket"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Denne enheten er koblet til VPN-er"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Jobbprofilen din er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Den personlige profilen din er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Denne enheten er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Enhetsadministrasjon"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Profilovervåking"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Nettverksovervåking"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktiver VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Koble fra VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Se retningslinjer"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT-administratoren din kan overvåke og administrere innstillinger, bedriftstilgang, apper, data som er tilknyttet denne enheten, og enhetens posisjonsinformasjon.\n\nKontakt IT-administratoren for å få mer informasjon."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Denne enheten tilhører organisasjonen din.\n\nIT-administratoren din kan overvåke og administrere innstillinger, bedriftstilgang, apper, data som er tilknyttet denne enheten, og enhetens posisjonsinformasjon.\n\nKontakt IT-administratoren for å få mer informasjon."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organisasjonen din installerte en sertifiseringsinstans på denne enheten. Den sikre nettverkstrafikken din kan overvåkes eller endres."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organisasjonen din installerte en sertifiseringsinstans i jobbprofilen din. Den sikre nettverkstrafikken din kan overvåkes eller endres."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"En sertifiseringsinstans er installert på denne enheten. Den sikre nettverkstrafikken din kan overvåkes eller endres."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Sett på pause"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Hopp til neste"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Hopp til forrige"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Endre størrelse"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon ble slått av pga varme"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefonen din kjører nå som normalt"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonen din var for varm, så den ble slått av for å kjøles ned. Telefonen din kjører nå som normalt.\n\nTelefonen kan blir for varm hvis du:\n • bruker ressurskrevende apper (for eksempel spill-, video- eller navigeringsapper)\n • laster store filer opp eller ned\n • bruker telefonen ved høy temperatur"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Bekreft endringen for <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Sveip for å se flere"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laster inn anbefalinger"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Medier"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den nåværende økten."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Feil. Prøver igjen …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke funnet"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index c7a3495a1a66..fdc36d52eb7d 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> का हकमा गरिएको परिवर्तन पुष्टि गर्नुहोस्"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"थप हेर्न स्वाइप गर्नुहोस्"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"मिडिया"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"हालको सत्र लुकाउनुहोस्।"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लुकाउनुहोस्"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"सुचारु गर्नुहोस्"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिङ"</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>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 196357c4794e..cb9e178de243 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -81,6 +81,8 @@
<color name="global_screenshot_dismiss_foreground">#FFFFFF</color>
<color name="global_screenshot_background_protection_start">#80000000</color> <!-- 50% black -->
+ <!-- Media -->
+ <color name="media_divider">#85ffffff</color>
<!-- Biometric dialog colors -->
<color name="biometric_dialog_gray">#ff888888</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index f6dd012528af..c7e0d6ecea07 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tik nog eens om te openen"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Veeg omhoog om te openen"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Veeg omhoog om het opnieuw te proberen"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Vegen voor telefoon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Vegen vanaf pictogram voor spraakassistent"</string>
<string name="camera_hint" msgid="4519495795000658637">"Vegen voor camera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiel kan worden gecontroleerd"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Netwerk kan worden gecontroleerd"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Netwerk kan worden gecontroleerd"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Je organisatie is eigenaar van dit apparaat en kan het netwerkverkeer bijhouden"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> is eigenaar van dit apparaat en kan het netwerkverkeer bijhouden"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Dit apparaat is eigendom van je organisatie en is verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> en is verbonden met <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Dit apparaat is eigendom van je organisatie"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Dit apparaat is eigendom van je organisatie en is verbonden met VPN\'s"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> en is verbonden met VPN\'s"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Je organisatie kan het netwerkverkeer in je werkprofiel bijhouden"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kan het netwerkverkeer in je werkprofiel bijhouden"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Netwerk kan worden bijgehouden"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Dit apparaat is verbonden met VPN\'s"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Je werkprofiel is verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Je persoonlijke profiel is verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Dit apparaat is verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Apparaatbeheer"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Profielcontrole"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Netwerkcontrole"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN uitschakelen"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Verbinding met VPN verbreken"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Beleid bekijken"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nJe IT-beheerder kan instellingen, zakelijke toegang, apps, aan je apparaat gekoppelde gegevens en de locatiegegevens van je apparaat bekijken en beheren.\n\nNeem contact op met je IT-beheerder voor meer informatie."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Dit apparaat is eigendom van je organisatie.\n\nJe IT-beheerder kan instellingen, zakelijke toegang, apps, aan je apparaat gekoppelde gegevens en de locatiegegevens van je apparaat bekijken en beheren.\n\nNeem contact op met je IT-beheerder voor meer informatie."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Je organisatie heeft een certificeringsinstantie geïnstalleerd op dit apparaat. Je beveiligde netwerkverkeer kan worden bijgehouden of aangepast."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Je organisatie heeft een certificeringsinstantie geïnstalleerd in je werkprofiel. Je beveiligde netwerkverkeer kan worden bijgehouden of aangepast."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Er is een certificeringsinstantie geïnstalleerd op dit apparaat. Je beveiligde netwerkverkeer kan worden bijgehouden of aangepast."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Onderbreken"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Doorgaan naar volgende"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Teruggaan naar vorige"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Formaat aanpassen"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefoon uitgezet wegens hitte"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Je telefoon presteert nu weer zoals gebruikelijk"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Je telefoon was te warm en is uitgeschakeld om af te koelen. Je telefoon presteert nu weer zoals gebruikelijk.\n\nJe telefoon kan warm worden als je:\n • bronintensieve apps gebruikt (zoals game-, video-, of navigatie-apps),\n • grote bestanden up- of downloadt,\n • je telefoon gebruikt bij hoge temperaturen."</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Bevestig de wijziging voor <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe om meer te zien"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Aanbevelingen laden"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"De huidige sessie verbergen."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Verbergen"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fout. Opnieuw proberen…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Niet gevonden"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 663ec9d47e45..95d6f5f5a154 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ପାଇଁ ପରିବର୍ତ୍ତନ ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ଅଧିକ ଦେଖିବାକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"ମିଡିଆ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"ବର୍ତ୍ତମାନର ସେସନ୍ ଲୁଚାନ୍ତୁ।"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ଲୁଚାନ୍ତୁ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</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>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index cc87d09f49ca..43ab5aae7d12 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ਲਈ ਤਬਦੀਲੀ ਦੀ ਤਸਦੀਕ ਕਰੋ"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ਹੋਰ ਦੇਖਣ ਲਈ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"ਮੀਡੀਆ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਨੂੰ ਲੁਕਾਓ।"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ਲੁਕਾਓ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 074f420d6f91..e4c98e0d807e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -946,8 +946,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Wstrzymaj"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Dalej"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Wstecz"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Zmień rozmiar"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon wyłączony: przegrzanie"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefon działa teraz normalnie"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon był zbyt gorący i wyłączył się, by obniżyć temperaturę. Urządzenie działa teraz normalnie.\n\nTelefon może się przegrzać, gdy:\n • Używasz aplikacji zużywających dużo zasobów (np. gier, nawigacji czy odtwarzaczy filmów)\n • Pobierasz lub przesyłasz duże pliki\n • Używasz telefonu w wysokiej temperaturze"</string>
@@ -1092,15 +1091,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Potwierdź zmianę dotyczącą urządzenia <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Przesuń palcem, by zobaczyć więcej"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Wczytuję rekomendacje"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Ukryj bieżącą sesję."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ukryj"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Wznów"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Ustawienia"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Błąd, próbuję jeszcze raz…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie znaleziono"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index ac523614ce33..334b19e6eda5 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Deslize a partir do ícone do telefone"</string>
<string name="voice_hint" msgid="7476017460191291417">"Deslize a partir do ícone de assistência de voz"</string>
<string name="camera_hint" msgid="4519495795000658637">"Deslize a partir do ícone da câmera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pode ser monitorado"</string>
<string name="vpn_footer" msgid="3457155078010607471">"A rede pode ser monitorada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"A rede pode ser monitorada"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence à sua organização e está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está conectado a <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Este dispositivo pertence à sua organização"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Este dispositivo pertence à sua organização e está conectado a VPNs"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está conectado a VPNs"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Sua organização pode monitorar o tráfego de rede no seu perfil de trabalho"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> pode monitorar o tráfego de rede no seu perfil de trabalho"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"A rede pode ser monitorada"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Este dispositivo está conectado a VPNs"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Seu perfil de trabalho está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Seu perfil pessoal está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Este dispositivo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gerenciamento de dispositivos"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Monitoramento de perfis"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Monitoramento de rede"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Desativar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence à sua organização.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Sua organização instalou uma autoridade de certificação neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Sua organização instalou uma autoridade de certificação no seu perfil de trabalho. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Uma autoridade de certificação foi instalada neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausar"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Pular para a próxima"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Pular para a anterior"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Redimensionar"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"O smartphone foi desligado devido ao aquecimento"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"O smartphone está sendo executado normalmente agora"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O smartphone estava muito quente e foi desligado para resfriar. Agora, ele está sendo executado normalmente.\n\nO smartphone pode ficar quente demais se você:\n • usar apps que consomem muitos recursos (como apps de jogos, vídeos ou navegação);\n • fizer o download ou upload de arquivos grandes;\n • usar o smartphone em temperaturas altas."</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirme a mudança para <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize para ver mais"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f23e0a8ff05c..512057febe63 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Deslize rapidamente para cima para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Deslize rapidamente para cima para tentar novamente."</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua entidade."</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
<string name="phone_hint" msgid="6682125338461375925">"Deslize rapid. a partir do ícone para aceder ao telemóvel"</string>
<string name="voice_hint" msgid="7476017460191291417">"Deslize rapid. a partir do ícone para aceder ao assist. voz"</string>
<string name="camera_hint" msgid="4519495795000658637">"Deslize rapidamente a partir do ícone para aceder à câmara"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pode ser monitorizado"</string>
<string name="vpn_footer" msgid="3457155078010607471">"A rede pode ser monitorizada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"A rede pode ser monitorizada"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"A sua entidade gere este dispositivo e pode monitorizar o tráfego de rede."</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A entidade <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é proprietária deste dispositivo e pode monitorizar o tráfego de rede."</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence à sua entidade e está ligado a <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está ligado a <xliff:g id="VPN_APP">%2$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Este dispositivo pertence à sua entidade."</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Este dispositivo pertence à sua entidade e está ligado a VPNs."</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está ligado a VPNs."</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"A sua entidade pode monitorizar o tráfego de rede no seu perfil de trabalho"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"A <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> pode monitorizar o tráfego de rede no seu perfil de trabalho"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"A rede pode ser monitorizada"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Este dispositivo está ligado a VPNs."</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"O seu perfil de trabalho está ligado a <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"O seu perfil pessoal está ligado a <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Este dispositivo está ligado a <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gestão de dispositivos"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Monitorização de perfis"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Monitorização da rede"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Desativar a VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desligar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver Políticas"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO administrador de TI pode monitorizar e gerir as definições, o acesso empresarial, as apps, os dados associados ao dispositivo e as informações de localização do mesmo.\n\nContacte o administrador de TI para obter mais informações."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence à sua entidade.\n\nO administrador de TI pode monitorizar e gerir as definições, o acesso empresarial, as apps, os dados associados ao dispositivo e as informações de localização do mesmo.\n\nContacte o administrador de TI para obter mais informações."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"A sua entidade instalou uma autoridade de certificação neste dispositivo. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"A sua entidade instalou uma autoridade de certificação no seu perfil de trabalho. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Está instalada uma autoridade de certificação neste dispositivo. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
@@ -936,8 +920,7 @@
<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>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Redimensionar"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telem. deslig. devido ao calor"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"O telemóvel está a funcionar normalmente"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O telemóvel estava muito quente, por isso desligou-se para arrefecer. Agora funciona normalmente.\n\nO telemóvel pode sobreaquecer se:\n • Utilizar aplicações que utilizam mais recursos (jogos, vídeo ou aplicações de navegação)\n • Transferir ou carregar ficheiros grandes\n • Utilizar em altas temperaturas"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirme a alteração para <xliff:g id="DEVICE">%s</xliff:g>."</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize rapidamente para ver mais."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"A carregar recomendações…"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Oculte a sessão atual."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. A tentar novamente…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index ac523614ce33..334b19e6eda5 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Deslize a partir do ícone do telefone"</string>
<string name="voice_hint" msgid="7476017460191291417">"Deslize a partir do ícone de assistência de voz"</string>
<string name="camera_hint" msgid="4519495795000658637">"Deslize a partir do ícone da câmera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pode ser monitorado"</string>
<string name="vpn_footer" msgid="3457155078010607471">"A rede pode ser monitorada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"A rede pode ser monitorada"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence à sua organização e está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está conectado a <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Este dispositivo pertence à sua organização"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Este dispositivo pertence à sua organização e está conectado a VPNs"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e está conectado a VPNs"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Sua organização pode monitorar o tráfego de rede no seu perfil de trabalho"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> pode monitorar o tráfego de rede no seu perfil de trabalho"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"A rede pode ser monitorada"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Este dispositivo está conectado a VPNs"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Seu perfil de trabalho está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Seu perfil pessoal está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Este dispositivo está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gerenciamento de dispositivos"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Monitoramento de perfis"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Monitoramento de rede"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Desativar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence à sua organização.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Sua organização instalou uma autoridade de certificação neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Sua organização instalou uma autoridade de certificação no seu perfil de trabalho. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Uma autoridade de certificação foi instalada neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausar"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Pular para a próxima"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Pular para a anterior"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Redimensionar"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"O smartphone foi desligado devido ao aquecimento"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"O smartphone está sendo executado normalmente agora"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O smartphone estava muito quente e foi desligado para resfriar. Agora, ele está sendo executado normalmente.\n\nO smartphone pode ficar quente demais se você:\n • usar apps que consomem muitos recursos (como apps de jogos, vídeos ou navegação);\n • fizer o download ou upload de arquivos grandes;\n • usar o smartphone em temperaturas altas."</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Confirme a mudança para <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize para ver mais"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a85b6f1906d2..e5a9db0562bb 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -456,10 +456,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Atingeți din nou pentru a deschide"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Glisați în sus pentru a deschide"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Glisați pentru a încerca din nou"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Dispozitivul aparține organizației dvs."</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Acest dispozitiv aparține organizației <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Glisați dinspre telefon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Glisați dinspre pictogramă pentru asistentul vocal"</string>
<string name="camera_hint" msgid="4519495795000658637">"Glisați pentru a fotografia"</string>
@@ -526,33 +524,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilul poate fi monitorizat"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Rețeaua poate fi monitorizată"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Este posibil ca rețeaua să fie monitorizată"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizația dvs. gestionează acest dispozitiv și poate monitoriza traficul de rețea"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> deține acest dispozitiv și poate monitoriza traficul din rețea"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Dispozitivul aparține organizației dvs. și este conectat la <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Dispozitivul aparține organizației <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> și este conectat la <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Dispozitivul aparține organizației dvs."</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Acest dispozitiv aparține organizației <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Dispozitivul aparține organizației dvs. și este conectat la VPN-uri"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Dispozitivul aparține organizației <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> și este conectat la VPN-uri"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Este posibil ca organizația dvs. să monitorizeze traficul de rețea în profilul dvs. de serviciu"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Este posibil ca <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> să monitorizeze traficul de rețea din profilul dvs. de serviciu"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Este posibil ca rețeaua să fie monitorizată"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Dispozitivul este conectat la VPN-uri"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Profilul dvs. de serviciu este conectat la <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Profilul dvs. personal este conectat la <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Dispozitivul este conectat la <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gestionarea dispozitivului"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Monitorizarea profilului"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Monitorizarea rețelei"</string>
@@ -562,10 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Dezactivați conexiunea prin VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Deconectați rețeaua VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Afișați politicile"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Dispozitivul aparține organizației <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministratorul dvs. IT poate să monitorizeze și să gestioneze setările, accesul la nivelul companiei, aplicațiile, datele asociate dispozitivului și informațiile despre locația dispozitivului.\n\nPentru mai multe informații, contactați administratorul IT."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Dispozitivul aparține organizației dvs.\n\nAdministratorul dvs. IT poate să monitorizeze și să gestioneze setările, accesul la nivelul companiei, aplicațiile, datele asociate dispozitivului și informațiile despre locația dispozitivului.\n\nPentru mai multe informații, contactați administratorul IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizația dvs. a instalat un certificat CA pe acest dispozitiv. Traficul dvs. sigur de rețea poate fi monitorizat sau modificat."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizația dvs. a instalat un certificat CA în profilul dvs. de serviciu. Traficul dvs. sigur de rețea poate fi monitorizat sau modificat."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Pe acest dispozitiv este instalat un certificat CA. Traficul dvs. sigur de rețea poate fi monitorizat sau modificat."</string>
@@ -941,8 +925,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Întrerupeți"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Treceți la următorul"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Treceți la cel anterior"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Redimensionați"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefonul s-a oprit din cauza încălzirii"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Acum telefonul funcționează normal"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonul se încălzise prea mult și s-a oprit pentru a se răci. Acum telefonul funcționează normal.\n\nTelefonul s-ar putea încălzi prea mult dacă:\n • folosiți aplicații care consumă multe resurse (de ex., jocuri, aplicații video/de navigare);\n • descărcați/încărcați fișiere mari;\n • folosiți telefonul la temperaturi ridicate."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 6e4cb7c0c938..5352ab4f80c6 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -458,10 +458,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Нажмите ещё раз, чтобы открыть"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Проведите вверх, чтобы открыть"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Чтобы повторить попытку, проведите вверх"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Это устройство принадлежит вашей организации"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Этим устройством владеет организация \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string>
<string name="phone_hint" msgid="6682125338461375925">"Телефон: проведите от значка"</string>
<string name="voice_hint" msgid="7476017460191291417">"Аудиоподсказки: проведите от значка"</string>
<string name="camera_hint" msgid="4519495795000658637">"Камера: проведите от значка"</string>
@@ -529,33 +527,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Действия в профиле могут отслеживаться"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Сеть может отслеживаться"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Сеть может отслеживаться"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ваша организация управляет этим устройством и может отслеживать сетевой трафик"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Организация \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\" управляет этим устройством и может отслеживать сетевой трафик"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Это устройство принадлежит вашей организации и подключено к приложению \"<xliff:g id="VPN_APP">%1$s</xliff:g>\""</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Это устройство принадлежит организации \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\" и подключено к приложению \"<xliff:g id="VPN_APP">%2$s</xliff:g>\""</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Это устройство принадлежит вашей организации"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Это устройство принадлежит организации \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\""</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Это устройство принадлежит вашей организации и подключено к приложениям для VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Это устройство принадлежит организации \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\" и подключено к приложениям для VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Ваша организация может отслеживать сетевой трафик в рабочем профиле"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Организация \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\" может отслеживать сетевой трафик в вашем рабочем профиле"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Сеть может отслеживаться"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Это устройство подключено к приложениям для VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Ваш рабочий профиль подключен к приложению \"<xliff:g id="VPN_APP">%1$s</xliff:g>\""</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Ваш личный профиль подключен к приложению \"<xliff:g id="VPN_APP">%1$s</xliff:g>\""</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Это устройство подключено к приложению \"<xliff:g id="VPN_APP">%1$s</xliff:g>\""</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Управление устройством"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Мониторинг профиля"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Отслеживание сетей"</string>
@@ -565,10 +551,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Отключить VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Отключить VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Просмотреть политику"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Этим устройством управляет организация \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\".\n\nВаш системный администратор может управлять настройками, приложениями и параметрами доступа к корпоративным ресурсам на этом устройстве, а также связанными с ним данными (например, сведениями о местоположении).\n\nЗа подробной информацией обращайтесь к системному администратору."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Это устройство принадлежит вашей организации.\n\nСистемный администратор может управлять настройками, приложениями и параметрами доступа к корпоративным ресурсам на этом устройстве, а также связанными с ним данными (например, сведениями о местоположении).\n\nЗа подробной информацией обращайтесь к системному администратору."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ваша организация установила сертификат ЦС на устройство. Она может отслеживать и изменять защищенный сетевой трафик."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ваша организация установила сертификат ЦС в рабочем профиле. Она может отслеживать и изменять защищенный сетевой трафик."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На устройстве установлен сертификат ЦС. Ваш защищенный сетевой трафик могут отслеживать и изменять."</string>
@@ -946,8 +930,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Приостановить"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Перейти к следующему"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Перейти к предыдущему"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Изменить размер"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Телефон выключился из-за перегрева"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Сейчас телефон работает нормально"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Ваш телефон выключился из-за перегрева. Сейчас он работает нормально.\n\nВозможные причины перегрева телефона:\n • использование ресурсоемких игр и приложений, связанных с видео или навигацией);\n • скачивание или загрузка больших файлов;\n • высокая температура окружающей среды."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 6be0b31c41b0..162bea8050c1 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"විවෘත කිරීමට නැවත තට්ටු කරන්න"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"විවෘත කිරීමට ස්වයිප් කරන්න"</string>
<string name="keyguard_retry" msgid="886802522584053523">"නැවත උත්සාහ කිරීමට ඉහළට ස්වයිප් කරන්න"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> සංවිධානයට අයිතිය"</string>
<string name="phone_hint" msgid="6682125338461375925">"දුරකථනය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
<string name="voice_hint" msgid="7476017460191291417">"හඬ සහාය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
<string name="camera_hint" msgid="4519495795000658637">"කැමරාව සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ඇතැම් විට පැතිකඩ නිරීක්ෂණය කරන ලදි"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ඇතැම් විට ජාලය නිරීක්ෂණය විය හැක"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ඇතැම් විට ජාලය නිරීක්ෂණය විය හැක"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ඔබේ සංවිධානයට මෙම උපාංගය අයිති අතර ජාල තදබදය නිරීක්ෂණය කළ හැකිය"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට මෙම උපාංගය අයිති අතර ජාල තදබදය නිරීක්ෂණය කළ හැකිය"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"මෙම උපාංගය ඔබේ සංවිධානයට අයිති අතර <xliff:g id="VPN_APP">%1$s</xliff:g> වෙත සම්බන්ධ කර ඇත"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට අයිති අතර <xliff:g id="VPN_APP">%2$s</xliff:g> වෙත සම්බන්ධ කර ඇත"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට අයිතිය"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"මෙම උපාංගය ඔබේ සංවිධානයට අයිති අතර VPNs වෙත සම්බන්ධ කර ඇත"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට අයිති අතර VPNs වෙත සම්බන්ධ කර ඇත"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"ඔබගේ කාර්යාල පැතිකඩ තුළ ඔබේ සංවිධානය ජාල තදබදය නිරීක්ෂණය කිරීමට හැක"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ඔබේ කාර්යාල පැතිකඩ තුළ ජාල තදබදය නිරීක්ෂණය කළ හැක"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ඇතැම් විට ජාලය නිරීක්ෂණය විය හැක"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"මෙම උපාංගය VPNs වෙත සම්බන්ධ කර ඇත"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"ඔබේ කාර්යාල පැතිකඩ <xliff:g id="VPN_APP">%1$s</xliff:g> වෙත සම්බන්ධ කර ඇත"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"ඔබේ පෞද්ගලික පැතිකඩ <xliff:g id="VPN_APP">%1$s</xliff:g> වෙත සම්බන්ධ කර ඇත"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"මෙම උපාංගය <xliff:g id="VPN_APP">%1$s</xliff:g> වෙත සම්බන්ධ කර ඇත"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"උපාංග කළමනාකරණය"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"පැතිකඩ නිරීක්ෂණය කිරීම"</string>
<string name="monitoring_title" msgid="4063890083735924568">"ජාල නිරීක්ෂණය"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN අබල කරන්න."</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN විසන්ධි කරන්න"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ප්‍රතිපත්ති පෙන්වන්න"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට අයිතිය.\n\nඔබේ IT පරිපාලකට ඔබේ උපාංගය හා සම්බන්ධිත සැකසීම්, ආයතනික ප්‍රවේශය, යෙදුම්, දත්ත සහ ඔබේ උපාංගයේ ස්ථාන තොරතුරු නිරීක්ෂණය කර කළමනාකරණය කිරීමට හැකිය.\n\nවැඩිදුර තොරතුරු සඳහා, ඔබේ IT අමතන්න."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය.\n\nඔබේ IT පරිපාලකට ඔබේ උපාංගය හා සම්බන්ධිත සැකසීම්, ආයතනික ප්‍රවේශය, යෙදුම්, දත්ත සහ ඔබේ උපාංගයේ ස්ථාන තොරතුරු නිරීක්ෂණය කර කළමනාකරණය කිරීමට හැකිය.\n\nවැඩිදුර තොරතුරු සඳහා, ඔබේ IT අමතන්න."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ඔබගේ සංවිධානය ඔබගේ උපාංගය තුළ සහතික අධිකාරියක් ස්ථාපනය කර තිබේ. ඔබගේ ආරක්ෂක ජාල තදබදය නිරීක්ෂණය හෝ වෙනස් කිරීමට පුළුවනි."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"ඔබගේ සංවිධානය ඔබගේ කාර්යාල පැතිකඩ තුළ සහතික අධිකාරියක් ස්ථාපනය කර තිබේ. ඔබගේ ආරක්ෂක ජාල තදබදය නිරීක්ෂණය හෝ වෙනස් කිරීමට පුළුවනි."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"මෙම උපාංගය තුළ සහතික අධිකාරියක් ස්ථාපනය කර තිබේ. ඔබගේ ආරක්ෂක ජාල තදබදය නිරීක්ෂණය හෝ වෙනස් කිරීමට පුළුවනි."</string>
@@ -1079,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> සඳහා වෙනස තහවුරු කරන්න"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"තව බැලීමට ස්වයිප් කරන්න"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"නිර්දේශ පූරණය කරමින්"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"මාධ්‍ය"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"වත්මන් සැසිය සඟවන්න."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"සඟවන්න"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</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>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 0a6e22868511..bfd007593432 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -946,8 +946,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pozastaviť"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Preskočiť na ďalšie"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Preskočiť na predchádzajúce"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Zmeniť veľkosť"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefón sa vypol z dôvodu prehriatia"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Teraz telefón funguje ako obvykle"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefón bol príliš horúci, preto sa vypol, aby vychladol. Teraz funguje ako obvykle.\n\nTelefón sa môže príliš zahriať v týchto prípadoch:\n • používanie náročných aplikácií (napr. hier, videí alebo navigácie);\n • sťahovanie alebo nahrávanie veľkých súborov;\n • používanie telefónu pri vysokých teplotách."</string>
@@ -1092,15 +1091,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Potvrdenie zmeny zariadenia <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Potiahnutím zobrazíte ďalšie položky"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítavajú sa odporúčania"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Médiá"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Skryť aktuálnu reláciu."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skryť"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string>
<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>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6c66a5df074f..05c71431a030 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -458,10 +458,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Znova se dotaknite, da odprete"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Povlecite navzgor, da odprete"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Ta naprava pripada vaši organizaciji"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Povlecite z ikone za telefon"</string>
<string name="voice_hint" msgid="7476017460191291417">"Povlecite z ikone za glasovnega pomočnika"</string>
<string name="camera_hint" msgid="4519495795000658637">"Povlecite z ikone za fotoaparat"</string>
@@ -529,33 +527,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil je morda nadziran"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Omrežje je lahko nadzorovano"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Omrežje je morda nadzorovano"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizacija je lastnica te naprave in lahko nadzira omrežni promet"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Organizacija <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> je lastnica te naprave in lahko nadzira omrežni promet"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ta naprava pripada vaši organizaciji in je povezana v aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> in je povezana v aplikacijo <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Ta naprava pripada vaši organizaciji"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Ta naprava pripada vaši organizaciji in je povezana v omrežja VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> in je povezana v omrežja VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Vaša organizacija lahko nadzira omrežni promet v vašem delovnem profilu"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> lahko nadzira omrežni promet v vašem delovnem profilu"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Omrežje je morda nadzorovano"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Ta naprava je povezana v omrežja VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Vaš delovni profil je povezan v aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Vaš osebni profil je povezan v aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Ta naprava je povezava v aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Upravljanje naprav"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Nadzor nad profilom"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Nadzor omrežja"</string>
@@ -565,10 +551,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Onemogoči VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini povezavo z VPN-jem"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži pravilnike"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nSkrbnik za IT lahko nadzira in upravlja nastavitve, dostop za podjetje, aplikacije, z napravo povezane podatke in podatke o lokaciji naprave.\n\nZa več informacij se obrnite na skrbnika za IT."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Ta naprava pripada vaši organizaciji.\n\nSkrbnik za IT lahko nadzira in upravlja nastavitve, dostop za podjetje, aplikacije, z napravo povezane podatke in podatke o lokaciji naprave.\n\nZa več informacij se obrnite na skrbnika za IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Vaša organizacija je v to napravo namestila overitelja potrdil. Varni omrežni promet se lahko nadzira ali spreminja."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Vaša organizacija je v vaš delovni profil namestila overitelja potrdil. Varni omrežni promet se lahko nadzira ali spreminja."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"V tej napravi je nameščen overitelj potrdil. Varni omrežni promet se lahko nadzira ali spreminja."</string>
@@ -946,8 +930,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Začasno ustavi"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Preskoči na naslednjega"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Preskoči na prejšnjega"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Spremeni velikost"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Tel. izklopljen zaradi vročine"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Zdaj telefon normalno deluje"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon je bil prevroč, zato se je izklopil, da se ohladi. Zdaj normalno deluje.\n\nTelefon lahko postane prevroč ob:\n • uporabi aplikacij, ki intenzivno porabljajo sredstva (npr. za igranje iger, videoposnetke ali navigacijo)\n • prenosu ali nalaganju velikih datotek\n • uporabi telefona pri visokih temp."</string>
@@ -1092,15 +1075,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Potrdite spremembo za napravo <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Če si želite ogledati več, povlecite"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nalaganje priporočil"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Predstavnost"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Skrije trenutno sejo."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrij"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nadaljuj"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavitve"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Napaka, vnovični poskus …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ni mogoče najti"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 586f19f7cf07..184825c200ef 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Trokit përsëri për ta hapur"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Rrëshqit lart për ta hapur"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Rrëshqit për të hapur telefonin"</string>
<string name="voice_hint" msgid="7476017460191291417">"Rrëshqit për të hapur ndihmën zanore"</string>
<string name="camera_hint" msgid="4519495795000658637">"Rrëshqit për të hapur kamerën"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profili mund të monitorohet"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Rrjeti mund të jetë i monitoruar"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Rrjeti mund të jetë i monitoruar"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizata jote e zotëron këtë pajisje dhe mund të monitorojë trafikun e rrjetit"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e zotëron këtë pajisje dhe mund të monitorojë trafikun e rrjetit"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Kjo pajisje i përket organizatës sate dhe është e lidhur me <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> dhe është e lidhur me <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Kjo pajisje i përket organizatës sate"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Kjo pajisje i përket organizatës sate dhe është e lidhur me rrjetet VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> dhe është e lidhur me rrjetet VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Organizata jote mund të monitorojë trafikun e rrjetit në profilin tënd të punës"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> mund të monitorojë trafikun e rrjetit në profilin tënd të punës"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Rrjeti mund të jetë i monitoruar"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Kjo pajisje është e lidhur me rrjetet VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Profili yt i punës është i lidhur me <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Profili yt personal është i lidhur me <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Kjo pajisje është e lidhur me <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Menaxhimi i pajisjes"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Monitorimi i profilit"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Monitorimi i rrjetit"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Çaktivizo VPN-në"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Shkëput VPN-në"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Shiko politikat"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministratori i teknologjisë së informacionit mund të monitorojë dhe menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde.\n\nPër më shumë informacione, kontakto me administratorin e teknologjisë së informacionit."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Kjo pajisje i përket organizatës sate.\n\nAdministratori i teknologjisë së informacionit mund të monitorojë dhe menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde.\n\nPër më shumë informacione, kontakto me administratorin e teknologjisë së informacionit."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizata jote instaloi një autoritet certifikate në këtë pajisje. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Organizata jote instaloi një autoritet certifikate në profilin tënd të punës. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Në këtë pajisje është instaluar një autoritet certifikate. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Ndërprit"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Kalo te tjetra"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Kalo tek e mëparshmja"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Ndrysho përmasat"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefoni u fik për shkak të nxehtësisë"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefoni tani punon normalisht"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefoni yt ishte tepër i nxehtë, prandaj u fik për t\'u ftohur. Telefoni tani punon normalisht.\n\nTelefoni mund të nxehet së tepërmi nëse ti:\n • Përdor aplikacione intensive për burimet (siç janë aplikacionet e lojërave, videove apo aplikacionet e navigimit)\n • Shkarkon ose ngarkon skedarë të mëdhenj\n • E përdor telefonin në temperatura të larta"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Konfirmo ndryshimin për <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Rrëshqit shpejt për të shikuar më shumë"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Po ngarkon rekomandimet"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Fshih sesionin aktual."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fshih"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Gabim, po provohet përsëri"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nuk u gjet"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 9080887e037b..9be52e6cb40c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -456,10 +456,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Додирните поново да бисте отворили"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Превуците нагоре да бисте отворили"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Превуците нагоре да бисте пробали поново"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Овај уређај припада организацији"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Превуците од иконе за телефон"</string>
<string name="voice_hint" msgid="7476017460191291417">"Превуците од иконе за гласовну помоћ"</string>
<string name="camera_hint" msgid="4519495795000658637">"Превуците од иконе за камеру"</string>
@@ -526,33 +524,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профил се можда надгледа"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Мрежа се можда надгледа"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Мрежа се можда надгледа"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организација је власник уређаја и може да надгледа мрежни саобраћај"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> је власник овог уређаја и може да надгледа мрежни саобраћај"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Овај уређај припада организацији и повезан је са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> и повезан је са апликацијом <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Овај уређај припада организацији"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Овај уређај припада организацији и повезан је са VPN-овима"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> и повезан је са VPN-овима"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Организација може да прати мрежни саобраћај на пословном профилу"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> може да надгледа мрежни саобраћај на пословном профилу"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Мрежа се можда надгледа"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Овај уређај је повезан са VPN-овима"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Пословни профил је повезан са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Ваш лични профил је повезан са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Овај уређај је повезан са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Управљање уређајима"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Надгледање профила"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Надгледање мреже"</string>
@@ -562,10 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Онемогући VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Прекини везу са VPN-ом"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Прикажи смернице"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nИТ администратор може да надгледа подешавања, корпоративни приступ, апликације, податке повезане са уређајем и информације о локацији уређаја, као и да управља њима.\n\nВише информација потражите од ИТ администратора."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Овај уређај припада организацији.\n\nИТ администратор може да надгледа подешавања, корпоративни приступ, апликације, податке повезане са уређајем и информације о локацији уређаја, као и да управља њима.\n\nВише информација потражите од ИТ администратора."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Организација је на овом уређају инсталирала ауторитет за издавање сертификата. Безбедни мрежни саобраћај може да се прати или мења."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Организација је на пословном профилу инсталирала ауторитет за издавање сертификата. Безбедни мрежни саобраћај може да се прати или мења."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На овом уређају је инсталиран ауторитет за издавање сертификата. Безбедни мрежни саобраћај може да се прати или мења."</string>
@@ -941,8 +925,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Паузирај"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Пређи на следеће"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Пређи на претходно"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Промените величину"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Телефон се искључио због топлоте"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Телефон сада нормално ради"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Телефон је био преврућ, па се искључио да се охлади. Сада ради нормално.\n\nТелефон може превише да се угреје ако:\n • Користите апликације које захтевају пуно ресурса (нпр. видео игре, видео или апликације за навигацију)\n • Преузимате/отпремате велике датотеке\n • Користите телефон на високој температури"</string>
@@ -1086,15 +1069,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Потврдите промену за: <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Превуците да бисте видели још"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Учитавају се препоруке"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Медији"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Сакријте актуелну сесију."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сакриј"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</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>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 464234496c0a..f723c84fdfe3 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Pausa"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Hoppa till nästa"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Hoppa till föregående"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Ändra storlek"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Mobilen stängdes av pga. värme"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Mobilen fungerar nu som vanligt"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Mobilen var för varm och stängdes av för att kylas ned. Den fungerar nu som vanligt.\n\nMobilen kan bli för varm om du\n • använder resurskrävande appar (till exempel spel-, video- eller navigeringsappar)\n • laddar ned eller laddar upp stora filer\n • använder mobilen vid höga temperaturer."</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Bekräfta ändring av <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Svep om du vill se mer"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Rekommendationer läses in"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Dölj den aktuella sessionen."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Dölj"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fel, försöker igen …"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hittades inte"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 68253d45193f..2ae2b3c4e00f 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Gusa tena ili ufungue"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Telezesha kidole juu ili ufungue"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Telezesha kidole juu ili ujaribu tena"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Kifaa hiki kinamilikiwa na shirika lako"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telezesha kidole kutoka kwa aikoni ili ufikie simu"</string>
<string name="voice_hint" msgid="7476017460191291417">"Telezesha kidole kutoka aikoni ili upate mapendekezo ya sauti"</string>
<string name="camera_hint" msgid="4519495795000658637">"Telezesha kidole kutoka aikoni ili ufikie kamera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Huenda wasifu ukafuatiliwa"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Huenda mtandao unafuatiliwa"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Huenda mtandao unafuatiliwa"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Shirika lako linamiliki kifaa hiki na huenda likafuatilia trafiki ya mtandao"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> inamiliki kifaa hiki na huenda ikafuatilia trafiki ya mtandao"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Kifaa hiki kinamilikiwa na shirika lako na kimeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> na kimeunganishwa kwenye <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Kifaa hiki kinamilikiwa na shirika lako"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Kifaa hiki kinamilikiwa na shirika lako na kimeunganishwa kwenye VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> na kimeunganishwa kwenye VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Huenda shirika lako likafuatilia shughuli kwenye mtandao katika wasifu wako wa kazini"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Huenda <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ikafuatilia shughuli kwenye mtandao katika wasifu wako wa kazini"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Huenda mtandao unafuatiliwa"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Kifaa hiki kimeunganishwa kwenye VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Wasifu wako wa kazini umeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Wasifu wako wa binafsi umeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Kifaa hiki kimeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Udhibiti wa kifaa"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Ufuatiliaji wasifu"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Ufuatiliaji wa mtandao"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Zima VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Ondoa VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Angalia Sera"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nMsimamizi wako wa TEHAMA anaweza kufuatilia na kudhibiti mipangilio, ufikiaji wa maudhui ya shirika, programu, data inayohusiana na kifaa chako na maelezo kuhusu mahali kifaa chako kilipo.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako wa TEHAMA."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Kifaa hiki kinamilikiwa na shirika lako.\n\nMsimamizi wako wa TEHAMA anaweza kufuatilia na kudhibiti mipangilio, ufikiaji wa maudhui ya shirika, programu, data inayohusiana na kifaa chako na maelezo kuhusu mahali kifaa chako kilipo.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako wa TEHAMA."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Shirika lako limesakinisha mamlaka ya cheti kwenye kifaa hiki. Huenda shughuli kwenye mtandao wako salama zikafuatiliwa au kubadilishwa."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Shirika lako limesakinisha mamlaka ya cheti katika wasifu wako wa kazini. Huenda shughuli kwenye mtandao wako salama zikafuatiliwa au kubadilishwa."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Mamlaka ya cheti imesakinishwa kwenye kifaa hiki. Huenda shughuli kwenye mtandao wako salama zikafuatiliwa au kubadilishwa."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Sitisha"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Ruka ufikie inayofuata"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Ruka ufikie iliyotangulia"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Badilisha ukubwa"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Simu ilizima kutokana na joto"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Simu yako sasa inafanya kazi ipasavyo"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Simu yako ilikuwa moto sana, kwa hivyo ilijizima ili ipoe. Simu yako sasa inafanya kazi ipasavyo.\n\nSimu yako inaweza kuwa moto sana ikiwa:\n • Unatumia programu zinazotumia vipengee vingi (kama vile michezo ya video, video au programu za uelekezaji)\n • Unapakua au upakie faili kubwa\n • Unatumia simu yako katika maeneo yenye halijoto ya juu"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Thibitisha mabadiliko kwenye <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Telezesha kidole ili uone zaidi"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Inapakia mapendekezo"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Maudhui"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Ficha kipindi cha sasa."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ficha"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hitilafu, inajaribu tena…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hakipatikani"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 86d74442df88..b3f42f28a1d0 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"இடைநிறுத்து"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"அடுத்ததற்குச் செல்"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"முந்தையதற்குச் செல்"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"அளவு மாற்று"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"வெப்பத்தினால் ஃபோன் ஆஃப் செய்யப்பட்டது"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"உங்கள் ஃபோன் அதிகமாகச் சூடானதால், அதன் சூட்டைக் குறைக்க, ஆஃப் செய்யப்பட்டது. இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது.\n\nபின்வருவனவற்றைச் செய்தால், ஃபோன் சூடாகலாம்:\n • அதிகளவு தரவைப் பயன்படுத்தும் ஆப்ஸை (எ.கா: கேமிங், வீடியோ (அ) வழிகாட்டுதல் ஆப்ஸ்) பயன்படுத்துவது\n • பெரிய கோப்புகளைப் பதிவிறக்குவது/பதிவேற்றுவது\n • அதிக வெப்பநிலையில் ஃபோனைப் பயன்படுத்துவது"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ஐ மாற்றுவதை உறுதிப்படுத்தவும்"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"மேலும் பார்க்க ஸ்வைப் செய்யவும்"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"மீடியா"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"இந்த அமர்வை மறையுங்கள்."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"மறை"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</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>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b51c896107d2..ab8953dc8c31 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>కి సంబంధించి మార్పును నిర్ధారించండి"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"మరిన్నింటిని చూడటం కోసం స్వైప్ చేయండి"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"ప్రస్తుత సెషన్‌ను దాచు."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"దాచు"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్‌లు"</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>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 04a539929d16..8530da24077b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"หยุดชั่วคราว"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"ข้ามไปรายการถัดไป"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"ข้ามไปรายการก่อนหน้า"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"ปรับขนาด"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"โทรศัพท์ปิดไปเพราะร้อนมาก"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"ขณะนี้โทรศัพท์ทำงานเป็นปกติ"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"โทรศัพท์ร้อนเกินไปจึงปิดเครื่องเพื่อให้เย็นลง ขณะนี้โทรศัพท์ทำงานเป็นปกติ\n\nโทรศัพท์อาจร้อนเกินไปหากคุณ\n • ใช้แอปที่ใช้ทรัพยากรมาก (เช่น เกม วิดีโอ หรือแอปการนำทาง)\n • ดาวน์โหลดหรืออัปโหลดไฟล์ขนาดใหญ่\n • ใช้โทรศัพท์ในอุณหภูมิที่สูง"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"ยืนยันการเปลี่ยนแปลงสำหรับ<xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"เลื่อนเพื่อดูเพิ่มเติม"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"กำลังโหลดคำแนะนำ"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"สื่อ"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"ซ่อนเซสชันปัจจุบัน"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ซ่อน"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</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>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index be18cceab239..bfae370511bb 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"I-tap ulit upang buksan"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Mag-swipe pataas para buksan"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Mag-swipe pataas para subukan ulit"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ang device na ito"</string>
<string name="phone_hint" msgid="6682125338461375925">"Mag-swipe mula sa icon para sa telepono"</string>
<string name="voice_hint" msgid="7476017460191291417">"Mag-swipe mula sa icon para sa voice assist"</string>
<string name="camera_hint" msgid="4519495795000658637">"Mag-swipe mula sa icon para sa camera"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Maaaring subaybayan ang profile"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Maaaring sinusubaybayan ang network"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Maaaring sinusubaybayan ang network"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Pagmamay-ari ng organisasyon mo ang device na ito at puwede nitong subaybayan ang trapiko sa network"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito at puwede nitong subaybayan ang trapiko sa network"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Pagmamay-ari ng iyong organisasyon ang device na ito at nakakonekta ito sa <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito at nakakonekta ito sa <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Pagmamay-ari ng iyong organisasyon ang device na ito nakakonekta ito sa mga VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito at nakakonekta ito sa mga VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Maaaring sumubaybay ang iyong organisasyon ng trapiko sa network sa profile sa trabaho mo"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Maaaring subaybayan ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang trapiko sa network sa iyong profile sa trabaho"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Maaaring sinusubaybayan ang network"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Nakakonekta sa mga VPN ang device na ito"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Nakakonekta sa <xliff:g id="VPN_APP">%1$s</xliff:g> ang iyong profile sa trabaho"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Nakakonekta sa <xliff:g id="VPN_APP">%1$s</xliff:g> ang iyong personal na profile"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Nakakonekta sa <xliff:g id="VPN_APP">%1$s</xliff:g> ang device na ito"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Pamamahala ng device"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Pagsubaybay sa Profile"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Pagsubaybay sa network"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"I-disable ang VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Idiskonekta ang VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Tingnan ang Mga Patakaran"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito.\n\nMagagawa ng iyong IT admin na subaybayan at pamahalaan ang mga setting, pangkorporasyong access, mga app, data na nauugnay sa device mo, at ang impormasyon ng lokasyon ng iyong device.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa iyong IT admin."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Pagmamay-ari ng iyong organisasyon ang device na ito.\n\nMagagawa ng iyong IT admin na subaybayan at pamahalaan ang mga setting, pangkorporasyong access, mga app, data na nauugnay sa device mo, at ang impormasyon ng lokasyon ng iyong device.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa iyong IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Nag-install ang iyong organisasyon ng awtoridad sa certificate sa device na ito. Maaaring subaybayan o baguhin ang iyong ligtas na trapiko sa network."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Nag-install ang iyong organisasyon ng awtoridad sa certificate sa iyong profile sa trabaho. Maaaring subaybayan o baguhin ang iyong ligtas na trapiko sa network."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"May naka-install sa device na ito na isang awtoridad sa certificate. Maaaring subaybayan o baguhin ang iyong ligtas na trapiko sa network."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"I-pause"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Lumaktaw sa susunod"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Lumaktaw sa nakaraan"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"I-resize"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Na-off ang telepono dahil sa init"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Maayos na ngayong gumagana ang iyong telepono"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Napakainit ng telepono, kaya nag-off ito para lumamig. Maayos na itong gumagana.\n\nMaaaring lubos na uminit ang telepono kapag:\n • Gumamit ka ng resource-intensive na app (gaya ng app para sa gaming, video, o navigation)\n • Nag-download o nag-upload ka ng malaking file\n • Ginamit mo ito sa mainit na lugar"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Kumpirmahin ang pagbabago para sa <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Mag-swipe para tumingin ng higit pa"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nilo-load ang rekomendasyon"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Itago ang kasalukuyang session."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Itago"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Nagka-error, sinusubukan ulit…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hindi nahanap"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 815f13d0d689..4d7970601491 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Açmak için tekrar dokunun"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Açmak için yukarı kaydırın"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Tekrar denemek için yukarı kaydırın"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz, kuruluşunuza ait"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> adlı kuruluşa ait"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefon için, simgeden hızlıca kaydırın"</string>
<string name="voice_hint" msgid="7476017460191291417">"Sesli yardım için, simgeden hızlıca kaydırın"</string>
<string name="camera_hint" msgid="4519495795000658637">"Kamera için, simgeden hızlıca kaydırın"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil izlenebilir"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Ağ etkinliği izlenebilir"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Ağ etkinliği izlenebilir"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Bu cihaz, kuruluşunuza ait olup ağ trafiği kuruluşunuz tarafından izlenebilir"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Bu cihaz, <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> adlı kuruluşa ait olup ağ trafiği bu kuruluş tarafından izlenebilir"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Bu cihaz, kuruluşunuza ait olup <xliff:g id="VPN_APP">%1$s</xliff:g> uygulamasına bağlı"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Bu cihaz, <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kuruluşuna ait olup <xliff:g id="VPN_APP">%2$s</xliff:g> uygulamasına bağlı"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Bu cihaz, kuruluşunuza ait"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> adlı kuruluşa ait"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Bu cihaz, kuruluşunuza ait olup VPN\'lere bağlı."</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kuruluşuna ait olup VPN\'lere bağlı"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Kuruluşunuz, iş profilinizdeki ağ trafiğini izleyebilir"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, iş profilinizdeki ağ trafiğini izleyebilir"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Ağ trafiği izlenebilir"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Bu cihaz VPN\'lere bağlı"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"İş profiliniz <xliff:g id="VPN_APP">%1$s</xliff:g> uygulamasına bağlı"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Kişisel profiliniz <xliff:g id="VPN_APP">%1$s</xliff:g> uygulamasına bağlı"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Bu cihaz <xliff:g id="VPN_APP">%1$s</xliff:g> uygulamasına bağlı"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Cihaz yönetimi"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Profil izleme"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Ağ izleme"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN\'yi devre dışı bırak"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN bağlantısını kes"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Politikaları Göster"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> adlı kuruluşa ait.\n\nBT yöneticiniz cihazınızın ayarlarını, şirket erişimini, uygulamaları, cihazınızla ilişkilendirilen verileri, cihazınızın konum bilgilerini izleyip yönetebilir.\n\nDaha fazla bilgi için BT yöneticinize başvurun."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Bu cihaz kuruluşunuza ait.\n\nBT yöneticiniz cihazın ayarlarını, şirket erişimini, uygulamaları, cihazınızla ilişkilendirilen verileri, cihazınızın konum bilgilerini izleyip yönetebilir.\n\nDaha fazla bilgi için BT yöneticinize başvurun."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Kuruluşunuz bu cihaza bir sertifika yetkilisi yükledi. Güvenli ağ trafiğiniz izlenebilir veya değiştirilebilir."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Kuruluşunuz iş profilinize bir sertifika yetkilisi yükledi. Güvenli ağ trafiğiniz izlenebilir veya değiştirilebilir."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Bu cihazda bir sertifika yetkilisi yüklü. Güvenli ağ trafiğiniz izlenebilir veya değiştirilebilir."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Duraklat"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Sonrakine atla"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Öncekine atla"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Yeniden boyutlandır"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon ısındığından kapatıldı"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Telefonunuz şu anda normal bir şekilde çalışıyor"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonunuz çok ısındığından soğuması için kapatıldı ve şu anda normal bir şekilde çalışıyor.\n\nTelefon şu koşullarda çok ısınabilir:\n • Yoğun kaynak gerektiren uygulamalar (oyun, video veya gezinme uygulamaları gibi) kullanma\n • Büyük dosyalar indirme veya yükleme\n • Telefonu sıcak yerlerde kullanma"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> için değişikliği onaylayın"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Diğer öğeleri görmek için hızlıca kaydırın"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Öneriler yükleniyor"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Medya"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Mevcut oturumu gizle."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Gizle"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hata, yeniden deneniyor…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 6c777362a388..7ccd4620857b 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -946,8 +946,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Призупинити"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Перейти далі"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Перейти назад"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Змінити розмір"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Телефон перегрівся й вимкнувся"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Зараз телефон працює, як зазвичай"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Телефон перегрівся, тому вимкнувся, щоб охолонути. Зараз він працює, як зазвичай.\n\nТелефон перегрівається, якщо ви:\n • використовуєте ресурсомісткі додатки (ігри, відео, навігація)\n • завантажуєте великі файли на телефон або з нього\n • використовуєте телефон за високої температури"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 44d8435a6372..e8857c89d6c3 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1079,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> کی تبدیلی کی توثیق کریں"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"مزید دیکھنے کیلئے سوائپ کریں"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"میڈیا"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"موجودہ سیشن چھپائیں۔"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"چھپائیں"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</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>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 1f6612999e6f..bd7fb7d18f5e 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1063,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> uchun oʻzgarishlarni tasdiqlang"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Batafsil axborot olish uchun suring"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Joriy seans berkitilsin."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Berkitish"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Xato, qayta urinilmoqda…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Topilmadi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 1a0c651bd0d7..a3c643e41263 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Tạm dừng"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Chuyển tới mục tiếp theo"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Chuyển về mục trước"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Đổi kích thước"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Điện thoại đã tắt do nhiệt"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Điện thoại của bạn hiện đang chạy bình thường"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Do quá nóng nên điện thoại đã tắt để hạ nhiệt. Hiện điện thoại của bạn đang chạy bình thường.\n\nĐiện thoại có thể bị quá nóng nếu bạn:\n • Dùng các ứng dụng tốn nhiều tài nguyên (như ứng dụng trò chơi, video hoặc điều hướng)\n • Tải xuống hoặc tải lên tệp có dung lượng lớn\n • Dùng điện thoại ở nhiệt độ cao"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Xác nhận thay đổi <xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Vuốt để xem thêm"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Đang tải các đề xuất"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Nội dung nghe nhìn"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Ẩn phiên hiện tại."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ẩn"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Lỗi, đang thử lại…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Không tìm thấy"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 17c23098a03f..24c052312fb7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"暂停"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"跳到下一个"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"跳到上一个"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"调整大小"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"手机因严重发热而自动关机"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"现在,您的手机已恢复正常运行"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"由于发热严重,因此您的手机执行了自动关机以降温。现在,您的手机已恢复正常运行。\n\n以下情况可能会导致您的手机严重发热:\n • 使用占用大量资源的应用(例如游戏、视频或导航应用)\n • 下载或上传大型文件\n • 在高温环境下使用手机"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"确认<xliff:g id="DEVICE">%s</xliff:g>的更改"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"滑动可查看更多结构"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在加载推荐内容"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"媒体"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"隐藏当前会话。"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隐藏"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"继续播放"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"设置"</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>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 404e822e7151..8acba22917c3 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"暫停"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"跳到下一個"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"跳到上一個"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"調整大小"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"手機因過熱而關上"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"您的手機現已正常運作"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"您的手機之前因過熱而關上降溫。手機現已正常運作。\n\n以下情況可能會導致手機過熱:\n • 使用耗用大量資源的應用程式 (例如遊戲、影片或導航應用程式)\n • 下載或上載大型檔案\n • 在高溫環境下使用手機"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"確認<xliff:g id="DEVICE">%s</xliff:g>變更"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"滑動以查看更多"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</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>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 6db34044d851..f74e9de52758 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -936,8 +936,7 @@
<string name="pip_pause" msgid="1139598607050555845">"暫停"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"跳到下一個"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"跳到上一個"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"調整大小"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"手機先前過熱,因此關閉電源"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"手機現在已恢復正常運作"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"手機先前的溫度過高,因此關閉了電源以進行降溫。手機現在已恢復正常運作。\n\n以下情況可能會導致你的手機溫度過高:\n • 使用需要密集處理資料的應用程式 (例如遊戲、影片或導航應用程式)\n • 下載或上傳大型檔案\n • 在高溫環境下使用手機"</string>
@@ -1080,15 +1079,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"確認「<xliff:g id="DEVICE">%s</xliff:g>」的變更"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"滑動即可查看其他結構"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議控制項"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</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>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 8df33d93404a..46b35245221c 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -454,10 +454,8 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Thepha futhi ukuze uvule"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swayiphela phezulu ukuze uvule"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swayiphela phezulu ukuze uzame futhi"</string>
- <!-- no translation found for do_disclosure_generic (4896482821974707167) -->
- <skip />
- <!-- no translation found for do_disclosure_with_name (2091641464065004091) -->
- <skip />
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Le divayisi eyenhlangano yakho"</string>
+ <string name="do_disclosure_with_name" msgid="2091641464065004091">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swayiphela ifoni kusukela kusithonjana"</string>
<string name="voice_hint" msgid="7476017460191291417">"Swayiphela isilekeleli sezwi kusukela kusithonjana"</string>
<string name="camera_hint" msgid="4519495795000658637">"Swayiphela ikhamela kusukela kusithonjana"</string>
@@ -523,33 +521,21 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Iphrofayela ingaqashwa"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Inethiwekhi kungenzeka iqashiwe"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Inethiwekhi kungenzeka iqashiwe"</string>
- <!-- no translation found for quick_settings_disclosure_management_monitoring (8231336875820702180) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_monitoring (2831423806103479812) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_named_vpn (6096715329056415588) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_named_vpn (5302786161534380104) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management (5515296598440684962) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management (3476472755775165827) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_management_vpns (371835422690053154) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_management_vpns (4046375645500668555) -->
- <skip />
+ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Inhlangano yakho ingumnikazi wale divayisi futhi ingaqapha ithrafikhi yenethiwekhi"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"I-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ingumnikazi wale divayisi futhi ingaqapha ithrafikhi yenethiwekhi"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Le divayisi ngeyenhlangano yakho futhi ixhunywe ku-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="5302786161534380104">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> futhi ixhunywe ku-<xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Le divayisi eyenhlangano yakho"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"Le divayisi ngeyenhlangano yakho futhi ixhunywe kuma-VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> futhi ixhunywe kuma-VPN"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Inhlangano yakho ingaqapha ithrafikhi yenethiwekhi kuphrofayela yakho yomsebenzi"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"I-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ingaqaphela ithrafikhi yenethiwekhi kuphrofayela yakho yomsebenzi"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Inethiwekhi kungenzeka iqashiwe"</string>
- <!-- no translation found for quick_settings_disclosure_vpns (7213546797022280246) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_managed_profile_named_vpn (8117568745060010789) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_personal_profile_named_vpn (5481763430080807797) -->
- <skip />
- <!-- no translation found for quick_settings_disclosure_named_vpn (2350838218824492465) -->
- <skip />
+ <string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"Le divayisi ixhunywe kuma-VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Iphrofayela yakho yomsebenzi ixhunywe ku-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="5481763430080807797">"Iphrofayela yakho yomuntu ixhunywe ku-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="2350838218824492465">"Le divayisi ixhunywe ku-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Ukuphathwa kwedivayisi"</string>
<string name="monitoring_title_profile_owned" msgid="6301118649405449568">"Ukuqapha iphrofayela"</string>
<string name="monitoring_title" msgid="4063890083735924568">"Ukuqashwa kwenethiwekhi"</string>
@@ -559,10 +545,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Khubaza i-VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Nqamula i-VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Buka izinqubomgomo"</string>
- <!-- no translation found for monitoring_description_named_management (505833016545056036) -->
- <skip />
- <!-- no translation found for monitoring_description_management (4308879039175729014) -->
- <skip />
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYUmphathi wakho we-IT angakwazi ukugada nokulawula amasethingi, ukufinyelela kwenhlangano, izinhlelo zokusebenza, idatha ehlobene nedivayisi yakho, nolwazi lwendawo yedivayisi yakho.\n\nUkuze uthole ulwazi olwengeziwe, xhumana nomphathi wakho we-IT."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Le divayisi ngeyenhlangano.\n\nUmphathi wakho we-IT angakwazi ukugada nokulawula amasethingi, ukufinyelela kwenhlangano, izinhlelo zokusebenza, idatha ehlobene nedivayisi yakho, nolwazi lwendawo yedivayisi yakho.\n\nUkuze uthole ulwazi olwengeziwe, xhumana nomphathi wakho we-IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Inhlangano yakho ifake ukugunyazwa kwesitifiketi kule divayisi. Ithrafikhi yenethiwekhi yakho evikelekile kungenzeka iqashelwe noma ilungiswe."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Inhlangano yakho ifake ukugunyaza kwesitifiketi kuphrofayela yakho yomsebenzi. Ithrafikhi yenethiwekhi yakho evikelekile ingaqashwa noma ilungiswe."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Ukugunyaza kwesitifiketi kufakwe kule divayisi. Ithrafikhi yenethiwekhi yakho evikelekile ingaqashelwa noma ilungiswe."</string>
@@ -936,8 +920,7 @@
<string name="pip_pause" msgid="1139598607050555845">"Misa isikhashana"</string>
<string name="pip_skip_to_next" msgid="3864212650579956062">"Yeqela kokulandelayo"</string>
<string name="pip_skip_to_prev" msgid="3742589641443049237">"Yeqela kokwangaphambilini"</string>
- <!-- no translation found for accessibility_action_pip_resize (8237306972921160456) -->
- <skip />
+ <string name="accessibility_action_pip_resize" msgid="8237306972921160456">"Shintsha usayizi"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Ifoni ivaliwe ngenxa yokushisa"</string>
<string name="thermal_shutdown_message" msgid="7432744214105003895">"Ifoni yakho manje isebenza kahle"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Ifoni yakho ibishisa kakhulu, ngakho-ke yacisha ukuze iphole. Ifoni yakho manje isebenza ngokuvamile.\n\nIfoni yakho ingashisa kakhulu uma:\n • Usebenzisa izinhlelo zokusebenza ezinkulu (njegegeyimu, ividiyo, noma izinhlelo zokusebenza zokuzula)\n • Landa noma layisha amafayela amakhulu\n • Sebenzisa ifoni yakho kumathempelesha aphezulu"</string>
@@ -1080,15 +1063,11 @@
<string name="controls_confirmation_message" msgid="7744104992609594859">"Qinisekisa ushintsho lwe-<xliff:g id="DEVICE">%s</xliff:g>"</string>
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swayipha ukuze ubone okuningi"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ilayisha izincomo"</string>
- <!-- no translation found for controls_media_title (1746947284862928133) -->
- <skip />
- <!-- no translation found for controls_media_close_session (3957093425905475065) -->
- <skip />
- <!-- no translation found for controls_media_dismiss_button (4485675693008031646) -->
- <skip />
+ <string name="controls_media_title" msgid="1746947284862928133">"Imidiya"</string>
+ <string name="controls_media_close_session" msgid="3957093425905475065">"Fihla iseshini yamanje."</string>
+ <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fihla"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string>
- <!-- no translation found for controls_media_settings_button (5815790345117172504) -->
- <skip />
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Iphutha, iyazama futhi…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ayitholakali"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d8a3c8c19eae..994a18110260 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -248,6 +248,8 @@
<color name="media_secondary_text">#99ffffff</color> <!-- 60% -->
<color name="media_seekbar_progress">#c0ffffff</color>
<color name="media_disabled">#80ffffff</color>
+ <color name="media_seamless_border">#26ffffff</color> <!-- 15% -->
+ <color name="media_divider">#1d000000</color>
<!-- controls -->
<color name="control_primary_text">#E6FFFFFF</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index df531a9c3e47..29a2ad4cba9f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1274,6 +1274,8 @@
<dimen name="qs_seamless_fallback_end_margin">16dp</dimen>
<dimen name="qqs_media_spacing">16dp</dimen>
<dimen name="qs_footer_horizontal_margin">22dp</dimen>
+ <dimen name="qs_media_disabled_seekbar_height">1dp</dimen>
+ <dimen name="qs_media_enabled_seekbar_height">3dp</dimen>
<dimen name="magnification_border_size">5dp</dimen>
<dimen name="magnification_frame_move_short">5dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0e3fa1e48695..db45a60ab7c0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2744,6 +2744,9 @@
<!-- Controls management favorites screen, See other apps with changes made [CHAR LIMIT=NONE] -->
<string name="controls_favorite_toast_no_changes">Changes not saved</string>
+ <!-- Controls management favorites screen. See other apps button [CHAR LIMIT=30] -->
+ <string name="controls_favorite_see_other_apps">See other apps</string>
+
<!-- Controls management controls screen error on load message [CHAR LIMIT=NONE] -->
<string name="controls_favorite_load_error">Controls could not be loaded. Check the <xliff:g id="app" example="System UI">%s</xliff:g> app to make sure that the app settings haven\u2019t changed.</string>
<!-- Controls management controls screen no controls found on load message [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/xml/media_collapsed.xml b/packages/SystemUI/res/xml/media_collapsed.xml
index 0e886d6fa0b8..811e0e351bd3 100644
--- a/packages/SystemUI/res/xml/media_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_collapsed.xml
@@ -85,7 +85,7 @@
app:layout_constraintTop_toBottomOf="@id/app_name"
app:layout_constraintBottom_toTopOf="@id/header_artist"
app:layout_constraintStart_toEndOf="@id/album_art"
- app:layout_constraintEnd_toStartOf="@id/action0"
+ app:layout_constraintEnd_toStartOf="@id/media_action_barrier"
app:layout_constraintHorizontal_bias="0"/>
<!-- Artist name -->
@@ -97,7 +97,7 @@
android:layout_marginBottom="24dp"
app:layout_constraintTop_toBottomOf="@id/header_title"
app:layout_constraintStart_toStartOf="@id/header_title"
- app:layout_constraintEnd_toStartOf="@id/action0"
+ app:layout_constraintEnd_toStartOf="@id/media_action_barrier"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0"/>
@@ -128,15 +128,37 @@
/>
<Constraint
+ android:id="@+id/media_action_barrier"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="vertical"
+ app:layout_constraintTop_toTopOf="parent"
+ app:barrierDirection="start"
+ app:constraint_referenced_ids="media_action_guidebox,action0,action1,action2,action3,action4"
+ />
+
+ <Constraint
+ android:id="@+id/media_action_guidebox"
+ android:layout_width="0dp"
+ android:layout_height="48dp"
+ android:layout_marginTop="18dp"
+ android:visibility="invisible"
+ app:layout_constraintTop_toBottomOf="@id/app_name"
+ app:layout_constraintStart_toEndOf="@id/header_title"
+ app:layout_constraintEnd_toEndOf="parent"
+ />
+
+ <Constraint
android:id="@+id/action0"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="4dp"
- android:layout_marginTop="16dp"
+ android:layout_marginEnd="4dp"
+ android:layout_marginTop="18dp"
android:visibility="gone"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toBottomOf="@id/app_name"
- app:layout_constraintLeft_toRightOf="@id/header_title"
+ app:layout_constraintLeft_toLeftOf="@id/media_action_guidebox"
app:layout_constraintRight_toLeftOf="@id/action1"
>
</Constraint>
@@ -188,9 +210,10 @@
android:layout_marginEnd="4dp"
android:visibility="gone"
android:layout_marginTop="18dp"
+ app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toBottomOf="@id/app_name"
app:layout_constraintLeft_toRightOf="@id/action3"
- app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintRight_toRightOf="@id/media_action_guidebox"
>
</Constraint>
</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_expanded.xml b/packages/SystemUI/res/xml/media_expanded.xml
index 9b4caa430185..8432abcc16cb 100644
--- a/packages/SystemUI/res/xml/media_expanded.xml
+++ b/packages/SystemUI/res/xml/media_expanded.xml
@@ -182,6 +182,7 @@
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
+ app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toRightOf="@id/action3"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/action0"
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index a8bbdf6b68c9..6dc8322a5cf3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -71,6 +71,7 @@ class Bubble implements BubbleViewProvider {
// Items that are typically loaded later
private String mAppName;
private ShortcutInfo mShortcutInfo;
+ private String mMetadataShortcutId;
private BadgedImageView mIconView;
private BubbleExpandedView mExpandedView;
@@ -136,6 +137,7 @@ class Bubble implements BubbleViewProvider {
final int desiredHeight, final int desiredHeightResId, @Nullable final String title) {
Objects.requireNonNull(key);
Objects.requireNonNull(shortcutInfo);
+ mMetadataShortcutId = shortcutInfo.getId();
mShortcutInfo = shortcutInfo;
mKey = key;
mFlags = 0;
@@ -218,6 +220,14 @@ class Bubble implements BubbleViewProvider {
return mTitle;
}
+ String getMetadataShortcutId() {
+ return mMetadataShortcutId;
+ }
+
+ boolean hasMetadataShortcutId() {
+ return (mMetadataShortcutId != null && !mMetadataShortcutId.isEmpty());
+ }
+
/**
* Call when the views should be removed, ensure this is called to clean up ActivityView
* content.
@@ -350,9 +360,9 @@ class Bubble implements BubbleViewProvider {
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;
+ mShortcutInfo = (entry.getRanking() != null ? entry.getRanking().getShortcutInfo() : null);
+ mMetadataShortcutId = (entry.getBubbleMetadata() != null
+ ? entry.getBubbleMetadata().getShortcutId() : null);
if (entry.getRanking() != null) {
mIsVisuallyInterruptive = entry.getRanking().visuallyInterruptive();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index aa417191b204..ccfbd8f57df1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -483,12 +483,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
/**
- * Dispatches a back press into the expanded Bubble's ActivityView if its IME is visible,
- * causing it to hide.
+ * Hides the current input method, wherever it may be focused, via InputMethodManagerInternal.
*/
- public void hideImeFromExpandedBubble() {
- if (mStackView != null) {
- mStackView.hideImeFromExpandedBubble();
+ public void hideCurrentInputMethod() {
+ try {
+ mBarService.hideCurrentInputMethodForBubbles();
+ } catch (RemoteException e) {
+ e.printStackTrace();
}
}
@@ -693,8 +694,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (mStackView == null) {
mStackView = new BubbleStackView(
mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
- mSysUiState, this::onAllBubblesAnimatedOut,
- this::onImeVisibilityChanged);
+ mSysUiState, this::onAllBubblesAnimatedOut, this::onImeVisibilityChanged,
+ this::hideCurrentInputMethod);
mStackView.addView(mBubbleScrim);
if (mExpandListener != null) {
mStackView.setExpandListener(mExpandListener);
@@ -1589,7 +1590,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@Override
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
if (mStackView != null && taskInfo.displayId == getExpandedDisplayId(mContext)) {
- mBubbleData.setExpanded(false);
+ if (mImeVisible) {
+ hideCurrentInputMethod();
+ } else {
+ mBubbleData.setExpanded(false);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 7020f1cb88eb..acbde9fa3efa 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -366,11 +366,15 @@ public class BubbleData {
validShortcutIds.add(info.getId());
}
- final Predicate<Bubble> invalidBubblesFromPackage = bubble ->
- packageName.equals(bubble.getPackageName())
- && (bubble.getShortcutInfo() == null
- || !bubble.getShortcutInfo().isEnabled()
- || !validShortcutIds.contains(bubble.getShortcutInfo().getId()));
+ final Predicate<Bubble> invalidBubblesFromPackage = bubble -> {
+ final boolean bubbleIsFromPackage = packageName.equals(bubble.getPackageName());
+ final boolean hasShortcutIdAndValidShortcut =
+ bubble.hasMetadataShortcutId()
+ && bubble.getShortcutInfo() != null
+ && bubble.getShortcutInfo().isEnabled()
+ && validShortcutIds.contains(bubble.getShortcutInfo().getId());
+ return bubbleIsFromPackage && !hasShortcutIdAndValidShortcut;
+ };
final Consumer<Bubble> removeBubble = bubble ->
dismissBubbleWithKey(bubble.getKey(), reason);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
index 390f7064a227..db64a13f3df3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
@@ -77,7 +77,7 @@ internal class BubbleDataRepository @Inject constructor(
BubbleEntity(
userId,
b.packageName,
- b.shortcutInfo?.id ?: return@mapNotNull null,
+ b.metadataShortcutId ?: return@mapNotNull null,
b.key,
b.rawDesiredHeight,
b.rawDesiredHeightResId,
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 7c3e027e2e65..b34312e2b473 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -173,7 +173,8 @@ public class BubbleExpandedView extends LinearLayout {
return;
}
try {
- if (!mIsOverflow && mBubble.getShortcutInfo() != null) {
+ if (!mIsOverflow && mBubble.hasMetadataShortcutId()
+ && mBubble.getShortcutInfo() != null) {
options.setApplyActivityFlagsForBubbles(true);
mActivityView.startShortcutActivity(mBubble.getShortcutInfo(),
options, null /* sourceBounds */);
@@ -465,7 +466,6 @@ public class BubbleExpandedView extends LinearLayout {
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- hideImeIfVisible();
mKeyboardVisible = false;
mNeedsNewHeight = false;
if (mActivityView != null) {
@@ -616,7 +616,7 @@ public class BubbleExpandedView extends LinearLayout {
if (isNew) {
mPendingIntent = mBubble.getBubbleIntent();
- if (mPendingIntent != null || mBubble.getShortcutInfo() != null) {
+ if (mPendingIntent != null || mBubble.hasMetadataShortcutId()) {
setContentVisibility(false);
mActivityView.setVisibility(VISIBLE);
}
@@ -788,7 +788,7 @@ public class BubbleExpandedView extends LinearLayout {
}
private boolean usingActivityView() {
- return (mPendingIntent != null || mBubble.getShortcutInfo() != null)
+ return (mPendingIntent != null || mBubble.hasMetadataShortcutId())
&& mActivityView != null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
index a888bd57c699..ffb650d62064 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
@@ -70,9 +70,6 @@ public class BubbleExperimentConfig {
private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps";
- private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow";
- private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = true;
-
/**
* When true, if a notification has the information necessary to bubble (i.e. valid
* contentIntent and an icon or image), then a {@link android.app.Notification.BubbleMetadata}
@@ -87,15 +84,6 @@ public class BubbleExperimentConfig {
}
/**
- * When true, show a menu with dismissed and aged-out bubbles.
- */
- static boolean allowBubbleOverflow(Context context) {
- return Settings.Secure.getInt(context.getContentResolver(),
- ALLOW_BUBBLE_OVERFLOW,
- ALLOW_BUBBLE_OVERFLOW_DEFAULT ? 1 : 0) != 0;
- }
-
- /**
* Same as {@link #allowAnyNotifToBubble(Context)} except it filters for notifications that
* are using {@link Notification.MessagingStyle} and have remote input.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index c985b083f9a9..09e879926f26 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -384,6 +384,11 @@ public class BubbleStackView extends FrameLayout
public final Consumer<Boolean> mOnImeVisibilityChanged;
/**
+ * Callback to run to ask BubbleController to hide the current IME.
+ */
+ private final Runnable mHideCurrentInputMethodCallback;
+
+ /**
* The currently magnetized object, which is being dragged and will be attracted to the magnetic
* dismiss target.
*
@@ -560,7 +565,7 @@ public class BubbleStackView extends FrameLayout
mMagneticTarget,
mIndividualBubbleMagnetListener);
- hideImeFromExpandedBubble();
+ hideCurrentInputMethod();
// Save the magnetized individual bubble so we can dispatch touch events to it.
mMagnetizedObject = mExpandedAnimationController.getMagnetizedBubbleDraggingOut();
@@ -732,7 +737,8 @@ public class BubbleStackView extends FrameLayout
FloatingContentCoordinator floatingContentCoordinator,
SysUiState sysUiState,
Runnable allBubblesAnimatedOutAction,
- Consumer<Boolean> onImeVisibilityChanged) {
+ Consumer<Boolean> onImeVisibilityChanged,
+ Runnable hideCurrentInputMethodCallback) {
super(context);
mBubbleData = data;
@@ -868,6 +874,7 @@ public class BubbleStackView extends FrameLayout
setUpOverflow();
mOnImeVisibilityChanged = onImeVisibilityChanged;
+ mHideCurrentInputMethodCallback = hideCurrentInputMethodCallback;
setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
onImeVisibilityChanged.accept(insets.getInsets(WindowInsets.Type.ime()).bottom > 0);
@@ -1145,9 +1152,6 @@ public class BubbleStackView extends FrameLayout
}
private void setUpOverflow() {
- if (!BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
- return;
- }
int overflowBtnIndex = 0;
if (mBubbleOverflow == null) {
mBubbleOverflow = new BubbleOverflow(getContext());
@@ -1504,6 +1508,7 @@ public class BubbleStackView extends FrameLayout
&& ((BadgedImageView) v).getKey().equals(bubble.getKey())) {
mBubbleContainer.removeViewAt(i);
bubble.cleanupViews();
+ updatePointerPosition();
logBubbleEvent(bubble, SysUiStatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
return;
}
@@ -1512,8 +1517,7 @@ public class BubbleStackView extends FrameLayout
}
private void updateOverflowVisibility() {
- if (!BubbleExperimentConfig.allowBubbleOverflow(mContext)
- || mBubbleOverflow == null) {
+ if (mBubbleOverflow == null) {
return;
}
mBubbleOverflow.setVisible(mIsExpanded ? VISIBLE : GONE);
@@ -1554,6 +1558,14 @@ public class BubbleStackView extends FrameLayout
mBubbleData.setShowingOverflow(true);
}
+ if (mIsExpanded && mIsExpansionAnimating) {
+ // If the bubble selection changed during the expansion animation, the expanding bubble
+ // probably crashed or immediately removed itself (or, we just got unlucky with a new
+ // auto-expanding bubble showing up at just the right time). Cancel the animations so we
+ // can start fresh.
+ cancelAllExpandCollapseSwitchAnimations();
+ }
+
// If we're expanded, screenshot the currently expanded bubble (before expanding the newly
// selected bubble) so we can animate it out.
if (mIsExpanded && mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
@@ -1584,6 +1596,8 @@ public class BubbleStackView extends FrameLayout
updatePointerPosition();
if (mIsExpanded) {
+ hideCurrentInputMethod();
+
// Make the container of the expanded view transparent before removing the expanded view
// from it. Otherwise a punch hole created by {@link android.view.SurfaceView} in the
// expanded view becomes visible on the screen. See b/126856255
@@ -1592,11 +1606,6 @@ public class BubbleStackView extends FrameLayout
if (previouslySelected != null) {
previouslySelected.setContentVisibility(false);
}
- if (previouslySelected != null && previouslySelected.getExpandedView() != null) {
- // Hide the currently expanded bubble's IME if it's visible before switching
- // to a new bubble.
- previouslySelected.getExpandedView().hideImeIfVisible();
- }
updateExpandedBubble();
requestUpdate();
@@ -1624,6 +1633,8 @@ public class BubbleStackView extends FrameLayout
return;
}
+ hideCurrentInputMethod();
+
mSysUiState
.setFlag(QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED, shouldExpand)
.commitUpdate(mContext.getDisplayId());
@@ -1807,12 +1818,12 @@ public class BubbleStackView extends FrameLayout
}
}
- void hideImeFromExpandedBubble() {
- if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
- // Hide the currently expanded bubble's IME if it's visible before switching to a new
- // bubble.
- mExpandedBubble.getExpandedView().hideImeIfVisible();
- }
+ /**
+ * Asks the BubbleController to hide the IME from anywhere, whether it's focused on Bubbles or
+ * not.
+ */
+ void hideCurrentInputMethod() {
+ mHideCurrentInputMethodCallback.run();
}
private void beforeExpandedViewAnimation() {
@@ -1879,35 +1890,37 @@ public class BubbleStackView extends FrameLayout
mExpandedBubble.getExpandedView().setSurfaceZOrderedOnTop(false);
}
- mDelayedAnimationHandler.postDelayed(() ->
- PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
- .spring(AnimatableScaleMatrix.SCALE_X,
- AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
- mScaleInSpringConfig)
- .spring(AnimatableScaleMatrix.SCALE_Y,
- AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
- mScaleInSpringConfig)
- .addUpdateListener((target, values) -> {
- if (mExpandedBubble.getIconView() == null) {
- return;
- }
- mExpandedViewContainerMatrix.postTranslate(
- mExpandedBubble.getIconView().getTranslationX()
- - bubbleWillBeAtX,
- 0);
- mExpandedViewContainer.setAnimationMatrix(
- mExpandedViewContainerMatrix);
- })
- .withEndActions(() -> {
- if (mExpandedBubble != null
- && mExpandedBubble.getExpandedView() != null) {
- mExpandedBubble.getExpandedView()
- .setContentVisibility(true);
- mExpandedBubble.getExpandedView()
- .setSurfaceZOrderedOnTop(false);
- }
- })
- .start(), startDelay);
+ mDelayedAnimationHandler.postDelayed(() -> {
+ PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
+ PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
+ .spring(AnimatableScaleMatrix.SCALE_X,
+ AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
+ mScaleInSpringConfig)
+ .spring(AnimatableScaleMatrix.SCALE_Y,
+ AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
+ mScaleInSpringConfig)
+ .addUpdateListener((target, values) -> {
+ if (mExpandedBubble == null || mExpandedBubble.getIconView() == null) {
+ return;
+ }
+ mExpandedViewContainerMatrix.postTranslate(
+ mExpandedBubble.getIconView().getTranslationX()
+ - bubbleWillBeAtX,
+ 0);
+ mExpandedViewContainer.setAnimationMatrix(
+ mExpandedViewContainerMatrix);
+ })
+ .withEndActions(() -> {
+ if (mExpandedBubble != null
+ && mExpandedBubble.getExpandedView() != null) {
+ mExpandedBubble.getExpandedView()
+ .setContentVisibility(true);
+ mExpandedBubble.getExpandedView()
+ .setSurfaceZOrderedOnTop(false);
+ }
+ })
+ .start();
+ }, startDelay);
}
private void animateCollapse() {
@@ -1927,10 +1940,6 @@ public class BubbleStackView extends FrameLayout
mAnimatingOutSurfaceContainer.setScaleX(0f);
mAnimatingOutSurfaceContainer.setScaleY(0f);
- if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
- mExpandedBubble.getExpandedView().hideImeIfVisible();
- }
-
// Let the expanded animation controller know that it shouldn't animate child adds/reorders
// since we're about to animate collapsed.
mExpandedAnimationController.notifyPreparingToCollapse();
@@ -2035,6 +2044,7 @@ public class BubbleStackView extends FrameLayout
return;
}
+ PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
.spring(AnimatableScaleMatrix.SCALE_X,
AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
@@ -2068,6 +2078,15 @@ public class BubbleStackView extends FrameLayout
mIsBubbleSwitchAnimating = false;
}
+ private void cancelAllExpandCollapseSwitchAnimations() {
+ cancelDelayedExpandCollapseSwitchAnimations();
+
+ PhysicsAnimator.getInstance(mAnimatingOutSurfaceView).cancel();
+ PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
+
+ mExpandedViewContainer.setAnimationMatrix(null);
+ }
+
private void notifyExpansionChanged(BubbleViewProvider bubble, boolean expanded) {
if (mExpandListener != null && bubble != null) {
mExpandListener.onBubbleExpandChanged(expanded, bubble.getKey());
@@ -2587,6 +2606,7 @@ public class BubbleStackView extends FrameLayout
bev.setContentVisibility(false);
mExpandedViewContainerMatrix.setScaleX(0f);
mExpandedViewContainerMatrix.setScaleY(0f);
+ mExpandedViewContainerMatrix.setTranslate(0f, 0f);
mExpandedViewContainer.setVisibility(View.INVISIBLE);
mExpandedViewContainer.setAlpha(0f);
mExpandedViewContainer.addView(bev);
@@ -2754,11 +2774,8 @@ public class BubbleStackView extends FrameLayout
* @return the number of bubbles in the stack view.
*/
public int getBubbleCount() {
- if (BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
- // Subtract 1 for the overflow button that is always in the bubble container.
- return mBubbleContainer.getChildCount() - 1;
- }
- return mBubbleContainer.getChildCount();
+ // Subtract 1 for the overflow button that is always in the bubble container.
+ return mBubbleContainer.getChildCount() - 1;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/AnimatableScaleMatrix.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/AnimatableScaleMatrix.java
index ae7833634794..07acb710c6d7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/AnimatableScaleMatrix.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/AnimatableScaleMatrix.java
@@ -134,4 +134,11 @@ public class AnimatableScaleMatrix extends Matrix {
public float getPivotY() {
return mPivotY;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ // Use object equality to allow this matrix to be used as a map key (which is required for
+ // PhysicsAnimator's animator caching).
+ return obj == this;
+ }
}
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 8e232520a196..f2a4f159f959 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -237,6 +237,10 @@ public class ExpandedAnimationController
}
mAfterExpand = null;
+
+ // Update bubble positions in case any bubbles were added or removed during the
+ // expansion animation.
+ updateBubblePositions();
};
} else {
after = () -> {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
index e105795ad57f..646e62062dfb 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -201,7 +201,7 @@ public class FalsingManagerFake implements FalsingManager {
}
@Override
- public void onNotificatonStopDismissing() {
+ public void onNotificationStopDismissing() {
}
@@ -211,7 +211,7 @@ public class FalsingManagerFake implements FalsingManager {
}
@Override
- public void onNotificatonStartDismissing() {
+ public void onNotificationStartDismissing() {
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index 37c7a2e3027f..cc64fb53f15f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -481,15 +481,15 @@ public class FalsingManagerImpl implements FalsingManager {
mDataCollector.onNotificationDismissed();
}
- public void onNotificatonStartDismissing() {
+ public void onNotificationStartDismissing() {
if (FalsingLog.ENABLED) {
- FalsingLog.i("onNotificatonStartDismissing", "");
+ FalsingLog.i("onNotificationStartDismissing", "");
}
mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS);
mDataCollector.onNotificatonStartDismissing();
}
- public void onNotificatonStopDismissing() {
+ public void onNotificationStopDismissing() {
mDataCollector.onNotificatonStopDismissing();
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 79b691bb3e37..ef2ef4570fca 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -302,8 +302,8 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
}
@Override
- public void onNotificatonStopDismissing() {
- mInternalFalsingManager.onNotificatonStopDismissing();
+ public void onNotificationStopDismissing() {
+ mInternalFalsingManager.onNotificationStopDismissing();
}
@Override
@@ -312,8 +312,8 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
}
@Override
- public void onNotificatonStartDismissing() {
- mInternalFalsingManager.onNotificatonStartDismissing();
+ public void onNotificationStartDismissing() {
+ mInternalFalsingManager.onNotificationStartDismissing();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index caab18712b0b..62254a64dfcc 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -380,7 +380,7 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
- public void onNotificatonStopDismissing() {
+ public void onNotificationStopDismissing() {
}
@Override
@@ -388,7 +388,7 @@ public class BrightLineFalsingManager implements FalsingManager {
}
@Override
- public void onNotificatonStartDismissing() {
+ public void onNotificationStartDismissing() {
updateInteractionType(Classifier.NOTIFICATION_DISMISS);
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt b/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
index 5891a7f705c8..f0356d038065 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
@@ -17,6 +17,7 @@
package com.android.systemui.controls
import android.content.ComponentName
+import android.graphics.drawable.Icon
import android.service.controls.Control
import android.service.controls.DeviceTypes
@@ -28,6 +29,7 @@ interface ControlInterface {
val subtitle: CharSequence
val removed: Boolean
get() = false
+ val customIcon: Icon?
@DeviceTypes.DeviceType val deviceType: Int
}
@@ -46,6 +48,9 @@ data class ControlStatus(
override val subtitle: CharSequence
get() = control.subtitle
+ override val customIcon: Icon?
+ get() = control.customIcon
+
@DeviceTypes.DeviceType override val deviceType: Int
get() = control.deviceType
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index a6af6a11d8b7..ec8bfc6fa2ae 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -73,7 +73,7 @@ class ControlsProviderLifecycleManager(
companion object {
private const val BIND_RETRY_DELAY = 1000L // ms
- private const val LOAD_TIMEOUT_SECONDS = 30L // seconds
+ private const val LOAD_TIMEOUT_SECONDS = 20L // seconds
private const val MAX_BIND_RETRIES = 5
private const val DEBUG = true
private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 05433197799e..c683a87d6282 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -238,7 +238,7 @@ internal class ControlHolder(
updateFavorite(!favorite.isChecked)
favoriteCallback(wrapper.controlId, favorite.isChecked)
}
- applyRenderInfo(renderInfo, wrapper.deviceType)
+ applyRenderInfo(renderInfo, wrapper)
}
override fun updateFavorite(favorite: Boolean) {
@@ -254,15 +254,19 @@ internal class ControlHolder(
return RenderInfo.lookup(itemView.context, component, deviceType)
}
- private fun applyRenderInfo(ri: RenderInfo, @DeviceTypes.DeviceType deviceType: Int) {
+ private fun applyRenderInfo(ri: RenderInfo, ci: ControlInterface) {
val context = itemView.context
val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())
- icon.setImageDrawable(ri.icon)
+ ci.customIcon?.let {
+ icon.setImageIcon(it)
+ } ?: run {
+ icon.setImageDrawable(ri.icon)
- // Do not color app icons
- if (deviceType != DeviceTypes.TYPE_ROUTINE) {
- icon.setImageTintList(fg)
+ // Do not color app icons
+ if (ci.deviceType != DeviceTypes.TYPE_ROUTINE) {
+ icon.setImageTintList(fg)
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index 4884781c64de..b2821579c389 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -174,30 +174,32 @@ class ControlsFavoritingActivity @Inject constructor(
subtitleView.visibility = View.GONE
} else {
statusText.visibility = View.GONE
- }
- pageIndicator.setNumPages(listOfStructures.size)
- pageIndicator.setLocation(0f)
- pageIndicator.visibility =
- if (listOfStructures.size > 1) View.VISIBLE else View.INVISIBLE
-
- ControlsAnimations.enterAnimation(pageIndicator).apply {
- addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- // Position the tooltip if necessary after animations are complete
- // so we can get the position on screen. The tooltip is not
- // rooted in the layout root.
- if (pageIndicator.visibility == View.VISIBLE &&
+
+ pageIndicator.setNumPages(listOfStructures.size)
+ pageIndicator.setLocation(0f)
+ pageIndicator.visibility =
+ if (listOfStructures.size > 1) View.VISIBLE else View.INVISIBLE
+
+ ControlsAnimations.enterAnimation(pageIndicator).apply {
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ // Position the tooltip if necessary after animations are complete
+ // so we can get the position on screen. The tooltip is not
+ // rooted in the layout root.
+ if (pageIndicator.visibility == View.VISIBLE &&
mTooltipManager != null) {
- val p = IntArray(2)
- pageIndicator.getLocationOnScreen(p)
- val x = p[0] + pageIndicator.width / 2
- val y = p[1] + pageIndicator.height
- mTooltipManager?.show(R.string.controls_structure_tooltip, x, y)
+ val p = IntArray(2)
+ pageIndicator.getLocationOnScreen(p)
+ val x = p[0] + pageIndicator.width / 2
+ val y = p[1] + pageIndicator.height
+ mTooltipManager?.show(
+ R.string.controls_structure_tooltip, x, y)
+ }
}
- }
- })
- }.start()
- ControlsAnimations.enterAnimation(structurePager).start()
+ })
+ }.start()
+ ControlsAnimations.enterAnimation(structurePager).start()
+ }
}
}, Consumer { runnable -> cancelLoadRunnable = runnable })
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
index 254395368bf9..4ef64a5cddbf 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.controls.management
import android.content.ComponentName
+import android.graphics.drawable.Icon
import androidx.recyclerview.widget.RecyclerView
import com.android.systemui.controls.ControlInterface
import com.android.systemui.controls.ControlStatus
@@ -126,9 +127,12 @@ data class ControlInfoWrapper(
get() = controlInfo.controlSubtitle
override val deviceType: Int
get() = controlInfo.deviceType
+ override val customIcon: Icon?
+ // Will need to address to support for edit activity
+ get() = null
}
data class DividerWrapper(
var showNone: Boolean = false,
var showDivider: Boolean = false
-) : ElementWrapper() \ No newline at end of file
+) : ElementWrapper()
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 865a38a2076c..0e4f68431c16 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -413,7 +413,9 @@ class ControlViewHolder(
control?.getCustomIcon()?.let {
// do not tint custom icons, assume the intended icon color is correct
- icon.imageTintList = null
+ if (icon.imageTintList != null) {
+ icon.imageTintList = null
+ }
icon.setImageIcon(it)
} ?: run {
if (drawable is StateListDrawable) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 951dc9936e1c..3bac196ca59f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -35,7 +35,6 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.ProximitySensor;
import com.android.systemui.util.wakelock.DelayedWakeLock;
@@ -56,9 +55,9 @@ public class DozeFactory {
private final DockManager mDockManager;
private final IWallpaperManager mWallpaperManager;
private final ProximitySensor mProximitySensor;
+ private final ProximitySensor.ProximityCheck mProximityCheck;
private final DelayedWakeLock.Builder mDelayedWakeLockBuilder;
private final Handler mHandler;
- private final DelayableExecutor mDelayableExecutor;
private final BiometricUnlockController mBiometricUnlockController;
private final BroadcastDispatcher mBroadcastDispatcher;
private final DozeHost mDozeHost;
@@ -69,9 +68,8 @@ public class DozeFactory {
AsyncSensorManager asyncSensorManager, AlarmManager alarmManager,
WakefulnessLifecycle wakefulnessLifecycle, KeyguardUpdateMonitor keyguardUpdateMonitor,
DockManager dockManager, @Nullable IWallpaperManager wallpaperManager,
- ProximitySensor proximitySensor,
+ ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proximityCheck,
DelayedWakeLock.Builder delayedWakeLockBuilder, @Main Handler handler,
- @Main DelayableExecutor delayableExecutor,
BiometricUnlockController biometricUnlockController,
BroadcastDispatcher broadcastDispatcher, DozeHost dozeHost) {
mFalsingManager = falsingManager;
@@ -85,9 +83,9 @@ public class DozeFactory {
mDockManager = dockManager;
mWallpaperManager = wallpaperManager;
mProximitySensor = proximitySensor;
+ mProximityCheck = proximityCheck;
mDelayedWakeLockBuilder = delayedWakeLockBuilder;
mHandler = handler;
- mDelayableExecutor = delayableExecutor;
mBiometricUnlockController = biometricUnlockController;
mBroadcastDispatcher = broadcastDispatcher;
mDozeHost = dozeHost;
@@ -112,8 +110,8 @@ public class DozeFactory {
new DozePauser(mHandler, machine, mAlarmManager, mDozeParameters.getPolicy()),
new DozeFalsingManagerAdapter(mFalsingManager),
createDozeTriggers(dozeService, mAsyncSensorManager, mDozeHost,
- mAlarmManager, config, mDozeParameters, mDelayableExecutor, wakeLock,
- machine, mDockManager, mDozeLog),
+ mAlarmManager, config, mDozeParameters, wakeLock,
+ machine, mDockManager, mDozeLog, mProximityCheck),
createDozeUi(dozeService, mDozeHost, wakeLock, machine, mHandler,
mAlarmManager, mDozeParameters, mDozeLog),
new DozeScreenState(wrappedService, mHandler, mDozeHost, mDozeParameters,
@@ -140,12 +138,13 @@ public class DozeFactory {
private DozeTriggers createDozeTriggers(Context context, AsyncSensorManager sensorManager,
DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
- DozeParameters params, DelayableExecutor delayableExecutor, WakeLock wakeLock,
- DozeMachine machine, DockManager dockManager, DozeLog dozeLog) {
+ DozeParameters params, WakeLock wakeLock,
+ DozeMachine machine, DockManager dockManager, DozeLog dozeLog,
+ ProximitySensor.ProximityCheck proximityCheck) {
boolean allowPulseTriggers = true;
return new DozeTriggers(context, machine, host, alarmManager, config, params,
- sensorManager, delayableExecutor, wakeLock, allowPulseTriggers, dockManager,
- mProximitySensor, dozeLog, mBroadcastDispatcher);
+ sensorManager, wakeLock, allowPulseTriggers, dockManager,
+ mProximitySensor, proximityCheck, dozeLog, mBroadcastDispatcher);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 6a5501445a4d..82639ba4375e 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -42,7 +42,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
-import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.ProximitySensor;
import com.android.systemui.util.wakelock.WakeLock;
@@ -153,8 +152,8 @@ public class DozeTriggers implements DozeMachine.Part {
public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
AlarmManager alarmManager, AmbientDisplayConfiguration config,
DozeParameters dozeParameters, AsyncSensorManager sensorManager,
- DelayableExecutor delayableExecutor, WakeLock wakeLock, boolean allowPulseTriggers,
- DockManager dockManager, ProximitySensor proximitySensor,
+ WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager,
+ ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proxCheck,
DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mMachine = machine;
@@ -168,7 +167,7 @@ public class DozeTriggers implements DozeMachine.Part {
config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
mDockManager = dockManager;
- mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, delayableExecutor);
+ mProxCheck = proxCheck;
mDozeLog = dozeLog;
mBroadcastDispatcher = broadcastDispatcher;
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
index 5f43e43c03c6..8ef20f89085c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
@@ -46,7 +46,9 @@ class KeyguardMediaController @Inject constructor(
})
}
- private var view: MediaHeaderView? = null
+ var visibilityChangedListener: ((Boolean) -> Unit)? = null
+ var view: MediaHeaderView? = null
+ private set
/**
* Attach this controller to a media view, initializing its state
@@ -54,9 +56,10 @@ class KeyguardMediaController @Inject constructor(
fun attach(mediaView: MediaHeaderView) {
view = mediaView
// First let's set the desired state that we want for this host
- mediaHost.visibleChangedListener = { updateVisibility() }
+ mediaHost.addVisibilityChangeListener { updateVisibility() }
mediaHost.expansion = 0.0f
mediaHost.showsOnlyActiveMedia = true
+ mediaHost.falsingProtectionNeeded = true
// Let's now initialize this view, which also creates the host view for us.
mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
@@ -70,6 +73,11 @@ class KeyguardMediaController @Inject constructor(
!bypassController.bypassEnabled &&
keyguardOrUserSwitcher &&
notifLockscreenUserManager.shouldShowLockscreenNotifications()
- view?.visibility = if (shouldBeVisible) View.VISIBLE else View.GONE
+ val previousVisibility = view?.visibility ?: View.GONE
+ val newVisibility = if (shouldBeVisible) View.VISIBLE else View.GONE
+ view?.visibility = newVisibility
+ if (previousVisibility != newVisibility) {
+ visibilityChangedListener?.invoke(shouldBeVisible)
+ }
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index bccc3abd8a27..e2215d57a094 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -1,42 +1,67 @@
package com.android.systemui.media
import android.content.Context
+import android.content.Intent
import android.graphics.Color
+import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
import android.view.LayoutInflater
-import android.view.GestureDetector
-import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
-import android.widget.HorizontalScrollView
import android.widget.LinearLayout
-import androidx.core.view.GestureDetectorCompat
import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
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.Utils
import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.animation.requiresRemeasuring
+import com.android.systemui.util.concurrency.DelayableExecutor
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
-private const val FLING_SLOP = 1000000
+private val settingsIntent = Intent().setAction(ACTION_MEDIA_CONTROLS_SETTINGS)
/**
* Class that is responsible for keeping the view carousel up to date.
* This also handles changes in state and applies them to the media carousel like the expansion.
*/
@Singleton
-class MediaViewManager @Inject constructor(
+class MediaCarouselController @Inject constructor(
private val context: Context,
private val mediaControlPanelFactory: Provider<MediaControlPanel>,
private val visualStabilityManager: VisualStabilityManager,
private val mediaHostStatesManager: MediaHostStatesManager,
+ private val activityStarter: ActivityStarter,
+ @Main executor: DelayableExecutor,
mediaManager: MediaDataCombineLatest,
- configurationController: ConfigurationController
+ configurationController: ConfigurationController,
+ mediaDataManager: MediaDataManager,
+ falsingManager: FalsingManager
) {
+ /**
+ * The current width of the carousel
+ */
+ private var currentCarouselWidth: Int = 0
+
+ /**
+ * The current height of the carousel
+ */
+ private var currentCarouselHeight: Int = 0
+
+ /**
+ * Are we currently showing only active players
+ */
+ private var currentlyShowingOnlyActive: Boolean = false
/**
+ * Is the player currently visible (at the end of the transformation
+ */
+ private var playersVisible: Boolean = false
+ /**
* The desired location where we'll be at the end of the transformation. Usually this matches
* the end location, except when we're still waiting on a state update call.
*/
@@ -73,17 +98,16 @@ class MediaViewManager @Inject constructor(
private var carouselMeasureHeight: Int = 0
private var playerWidthPlusPadding: Int = 0
private var desiredHostState: MediaHostState? = null
- private val mediaCarousel: HorizontalScrollView
+ private val mediaCarousel: MediaScrollView
+ private val mediaCarouselScrollHandler: MediaCarouselScrollHandler
val mediaFrame: ViewGroup
val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
+ private lateinit var settingsButton: View
private val mediaData: MutableMap<String, MediaData> = mutableMapOf()
private val mediaContent: ViewGroup
private val pageIndicator: PageIndicator
- private val gestureDetector: GestureDetectorCompat
private val visualStabilityCallback: VisualStabilityManager.Callback
- private var activeMediaIndex: Int = 0
private var needsReordering: Boolean = false
- private var scrollIntoCurrentMedia: Int = 0
private var currentlyExpanded = true
set(value) {
if (field != value) {
@@ -93,50 +117,25 @@ class MediaViewManager @Inject constructor(
}
}
}
- private val scrollChangedListener = object : View.OnScrollChangeListener {
- override fun onScrollChange(
- v: View?,
- scrollX: Int,
- scrollY: Int,
- oldScrollX: Int,
- oldScrollY: Int
- ) {
- if (playerWidthPlusPadding == 0) {
- return
- }
- onMediaScrollingChanged(scrollX / playerWidthPlusPadding,
- scrollX % playerWidthPlusPadding)
- }
- }
- private val gestureListener = object : GestureDetector.SimpleOnGestureListener() {
- override fun onFling(
- eStart: MotionEvent?,
- eCurrent: MotionEvent?,
- vX: Float,
- vY: Float
- ): Boolean {
- return this@MediaViewManager.onFling(eStart, eCurrent, vX, vY)
- }
- }
- private val touchListener = object : View.OnTouchListener {
- override fun onTouch(view: View, motionEvent: MotionEvent?): Boolean {
- return this@MediaViewManager.onTouch(view, motionEvent)
- }
- }
private val configListener = object : ConfigurationController.ConfigurationListener {
override fun onDensityOrFontScaleChanged() {
recreatePlayers()
+ inflateSettingsButton()
+ }
+
+ override fun onOverlayChanged() {
+ inflateSettingsButton()
}
}
init {
- gestureDetector = GestureDetectorCompat(context, gestureListener)
mediaFrame = inflateMediaCarousel()
mediaCarousel = mediaFrame.requireViewById(R.id.media_carousel_scroller)
pageIndicator = mediaFrame.requireViewById(R.id.media_page_indicator)
- mediaCarousel.setOnScrollChangeListener(scrollChangedListener)
- mediaCarousel.setOnTouchListener(touchListener)
- mediaCarousel.setOverScrollMode(View.OVER_SCROLL_NEVER)
+ mediaCarouselScrollHandler = MediaCarouselScrollHandler(mediaCarousel, pageIndicator,
+ executor, mediaDataManager::onSwipeToDismiss, this::updatePageIndicatorLocation,
+ falsingManager)
+ inflateSettingsButton()
mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
configurationController.addCallback(configListener)
visualStabilityCallback = VisualStabilityManager.Callback {
@@ -152,8 +151,15 @@ class MediaViewManager @Inject constructor(
mediaManager.addListener(object : MediaDataManager.Listener {
override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
oldKey?.let { mediaData.remove(it) }
- mediaData.put(key, data)
- addOrUpdatePlayer(key, oldKey, data)
+ if (!data.active && !Utils.useMediaResumption(context)) {
+ // This view is inactive, let's remove this! This happens e.g when dismissing /
+ // timing out a view. We still have the data around because resumption could
+ // be on, but we should save the resources and release this.
+ onMediaDataRemoved(key)
+ } else {
+ mediaData.put(key, data)
+ addOrUpdatePlayer(key, oldKey, data)
+ }
}
override fun onMediaDataRemoved(key: String) {
@@ -161,6 +167,11 @@ class MediaViewManager @Inject constructor(
removePlayer(key)
}
})
+ mediaFrame.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
+ // The pageIndicator is not laid out yet when we get the current state update,
+ // Lets make sure we have the right dimensions
+ updatePageIndicatorLocation()
+ }
mediaHostStatesManager.addCallback(object : MediaHostStatesManager.Callback {
override fun onHostStateChanged(location: Int, mediaHostState: MediaHostState) {
if (location == desiredLocation) {
@@ -170,6 +181,20 @@ class MediaViewManager @Inject constructor(
})
}
+ private fun inflateSettingsButton() {
+ val settings = LayoutInflater.from(context).inflate(R.layout.media_carousel_settings_button,
+ mediaFrame, false) as View
+ if (this::settingsButton.isInitialized) {
+ mediaFrame.removeView(settingsButton)
+ }
+ settingsButton = settings
+ mediaFrame.addView(settingsButton)
+ mediaCarouselScrollHandler.onSettingsButtonUpdated(settings)
+ settingsButton.setOnClickListener {
+ activityStarter.startActivity(settingsIntent, true /* dismissShade */)
+ }
+ }
+
private fun inflateMediaCarousel(): ViewGroup {
return LayoutInflater.from(context).inflate(R.layout.media_carousel,
UniqueObjectHostView(context), false) as ViewGroup
@@ -183,68 +208,7 @@ class MediaViewManager @Inject constructor(
mediaContent.addView(view, 0)
}
}
- updateMediaPaddings()
- updatePlayerVisibilities()
- }
-
- private fun onMediaScrollingChanged(newIndex: Int, scrollInAmount: Int) {
- val wasScrolledIn = scrollIntoCurrentMedia != 0
- scrollIntoCurrentMedia = scrollInAmount
- val nowScrolledIn = scrollIntoCurrentMedia != 0
- if (newIndex != activeMediaIndex || wasScrolledIn != nowScrolledIn) {
- activeMediaIndex = newIndex
- updatePlayerVisibilities()
- }
- val location = activeMediaIndex.toFloat() + if (playerWidthPlusPadding > 0)
- scrollInAmount.toFloat() / playerWidthPlusPadding else 0f
- pageIndicator.setLocation(location)
- }
-
- private fun onTouch(view: View, motionEvent: MotionEvent?): Boolean {
- if (gestureDetector.onTouchEvent(motionEvent)) {
- return true
- }
- if (motionEvent?.getAction() == MotionEvent.ACTION_UP) {
- val pos = mediaCarousel.scrollX % playerWidthPlusPadding
- if (pos > playerWidthPlusPadding / 2) {
- mediaCarousel.smoothScrollBy(playerWidthPlusPadding - pos, 0)
- } else {
- mediaCarousel.smoothScrollBy(-1 * pos, 0)
- }
- return true
- }
- return view.onTouchEvent(motionEvent)
- }
-
- private fun onFling(
- eStart: MotionEvent?,
- eCurrent: MotionEvent?,
- vX: Float,
- vY: Float
- ): Boolean {
- if (vX * vX < 0.5 * vY * vY) {
- return false
- }
- if (vX * vX < FLING_SLOP) {
- return false
- }
- val pos = mediaCarousel.scrollX
- val currentIndex = if (playerWidthPlusPadding > 0) pos / playerWidthPlusPadding else 0
- var destIndex = if (vX <= 0) currentIndex + 1 else currentIndex
- destIndex = Math.max(0, destIndex)
- destIndex = Math.min(mediaContent.getChildCount() - 1, destIndex)
- val view = mediaContent.getChildAt(destIndex)
- mediaCarousel.smoothScrollTo(view.left, mediaCarousel.scrollY)
- return true
- }
-
- private fun updatePlayerVisibilities() {
- val scrolledIn = scrollIntoCurrentMedia != 0
- for (i in 0 until mediaContent.childCount) {
- val view = mediaContent.getChildAt(i)
- val visible = (i == activeMediaIndex) || ((i == (activeMediaIndex + 1)) && scrolledIn)
- view.visibility = if (visible) View.VISIBLE else View.INVISIBLE
- }
+ mediaCarouselScrollHandler.onPlayersChanged()
}
private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData) {
@@ -259,6 +223,7 @@ class MediaViewManager @Inject constructor(
existingPlayer = mediaControlPanelFactory.get()
existingPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context),
mediaContent))
+ existingPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
mediaPlayers[key] = existingPlayer
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
@@ -280,28 +245,18 @@ class MediaViewManager @Inject constructor(
}
}
existingPlayer?.bind(data)
- updateMediaPaddings()
updatePageIndicator()
- updatePlayerVisibilities()
+ mediaCarouselScrollHandler.onPlayersChanged()
mediaCarousel.requiresRemeasuring = true
}
private fun removePlayer(key: String) {
val removed = mediaPlayers.remove(key)
removed?.apply {
- val beforeActive = mediaContent.indexOfChild(removed.view?.player) <=
- activeMediaIndex
+ mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
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()
+ mediaCarouselScrollHandler.onPlayersChanged()
updatePageIndicator()
}
}
@@ -317,20 +272,6 @@ class MediaViewManager @Inject constructor(
}
}
- private fun updateMediaPaddings() {
- val padding = context.resources.getDimensionPixelSize(R.dimen.qs_media_padding)
- val childCount = mediaContent.childCount
- for (i in 0 until childCount) {
- val mediaView = mediaContent.getChildAt(i)
- val desiredPaddingEnd = if (i == childCount - 1) 0 else padding
- val layoutParams = mediaView.layoutParams as ViewGroup.MarginLayoutParams
- if (layoutParams.marginEnd != desiredPaddingEnd) {
- layoutParams.marginEnd = desiredPaddingEnd
- mediaView.layoutParams = layoutParams
- }
- }
- }
-
private fun updatePageIndicator() {
val numPages = mediaContent.getChildCount()
pageIndicator.setNumPages(numPages, Color.WHITE)
@@ -342,6 +283,12 @@ class MediaViewManager @Inject constructor(
/**
* Set a new interpolated state for all players. This is a state that is usually controlled
* by a finger movement where the user drags from one state to the next.
+ *
+ * @param startLocation the start location of our state or -1 if this is directly set
+ * @param endLocation the ending location of our state.
+ * @param progress the progress of the transition between startLocation and endlocation. If
+ * this is not a guided transformation, this will be 1.0f
+ * @param immediately should this state be applied immediately, canceling all animations?
*/
fun setCurrentState(
@MediaLocation startLocation: Int,
@@ -349,9 +296,6 @@ class MediaViewManager @Inject constructor(
progress: Float,
immediately: Boolean
) {
- // Hack: Since the indicator doesn't move with the player expansion, just make it disappear
- // and then reappear at the end.
- pageIndicator.alpha = if (progress == 1f || progress == 0f) 1f else 0f
if (startLocation != currentStartLocation ||
endLocation != currentEndLocation ||
progress != currentTransitionProgress ||
@@ -363,6 +307,51 @@ class MediaViewManager @Inject constructor(
for (mediaPlayer in mediaPlayers.values) {
updatePlayerToState(mediaPlayer, immediately)
}
+ maybeResetSettingsCog()
+ }
+ }
+
+ private fun updatePageIndicatorLocation() {
+ // Update the location of the page indicator, carousel clipping
+ pageIndicator.translationX = (currentCarouselWidth - pageIndicator.width) / 2.0f +
+ mediaCarouselScrollHandler.contentTranslation
+ val layoutParams = pageIndicator.layoutParams as ViewGroup.MarginLayoutParams
+ pageIndicator.translationY = (currentCarouselHeight - pageIndicator.height -
+ layoutParams.bottomMargin).toFloat()
+ }
+
+ /**
+ * Update the dimension of this carousel.
+ */
+ private fun updateCarouselDimensions() {
+ var width = 0
+ var height = 0
+ for (mediaPlayer in mediaPlayers.values) {
+ val controller = mediaPlayer.mediaViewController
+ width = Math.max(width, controller.currentWidth)
+ height = Math.max(height, controller.currentHeight)
+ }
+ if (width != currentCarouselWidth || height != currentCarouselHeight) {
+ currentCarouselWidth = width
+ currentCarouselHeight = height
+ mediaCarouselScrollHandler.setCarouselBounds(currentCarouselWidth, currentCarouselHeight)
+ updatePageIndicatorLocation()
+ }
+ }
+
+ private fun maybeResetSettingsCog() {
+ val hostStates = mediaHostStatesManager.mediaHostStates
+ val endShowsActive = hostStates[currentEndLocation]?.showsOnlyActiveMedia
+ ?: true
+ val startShowsActive = hostStates[currentStartLocation]?.showsOnlyActiveMedia
+ ?: endShowsActive
+ if (currentlyShowingOnlyActive != endShowsActive ||
+ ((currentTransitionProgress != 1.0f && currentTransitionProgress != 0.0f) &&
+ startShowsActive != endShowsActive)) {
+ /// Whenever we're transitioning from between differing states or the endstate differs
+ // we reset the translation
+ currentlyShowingOnlyActive = endShowsActive
+ mediaCarouselScrollHandler.resetTranslation(animate = true)
}
}
@@ -404,6 +393,15 @@ class MediaViewManager @Inject constructor(
}
mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
}
+ mediaCarouselScrollHandler.showsSettingsButton = !it.showsOnlyActiveMedia
+ mediaCarouselScrollHandler.falsingProtectionNeeded = it.falsingProtectionNeeded
+ val nowVisible = it.visible
+ if (nowVisible != playersVisible) {
+ playersVisible = nowVisible
+ if (nowVisible) {
+ mediaCarouselScrollHandler.resetTranslation()
+ }
+ }
updateCarouselSize()
}
}
@@ -420,16 +418,7 @@ class MediaViewManager @Inject constructor(
carouselMeasureHeight = height
playerWidthPlusPadding = carouselMeasureWidth + context.resources.getDimensionPixelSize(
R.dimen.qs_media_padding)
- // The player width has changed, let's update the scroll position to make sure
- // it's still at the same place
- var newScroll = activeMediaIndex * playerWidthPlusPadding
- if (scrollIntoCurrentMedia > playerWidthPlusPadding) {
- newScroll += playerWidthPlusPadding -
- (scrollIntoCurrentMedia - playerWidthPlusPadding)
- } else {
- newScroll += scrollIntoCurrentMedia
- }
- mediaCarousel.scrollX = newScroll
+ mediaCarouselScrollHandler.playerWidthPlusPadding = playerWidthPlusPadding
// Let's remeasure the carousel
val widthSpec = desiredHostState?.measurementInput?.widthMeasureSpec ?: 0
val heightSpec = desiredHostState?.measurementInput?.heightMeasureSpec ?: 0
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
new file mode 100644
index 000000000000..993c05fbbd6f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.graphics.Outline
+import android.util.MathUtils
+import android.view.GestureDetector
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewOutlineProvider
+import androidx.core.view.GestureDetectorCompat
+import androidx.dynamicanimation.animation.FloatPropertyCompat
+import androidx.dynamicanimation.animation.SpringForce
+import com.android.settingslib.Utils
+import com.android.systemui.Gefingerpoken
+import com.android.systemui.qs.PageIndicator
+import com.android.systemui.R
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.util.animation.PhysicsAnimator
+import com.android.systemui.util.concurrency.DelayableExecutor
+
+private const val FLING_SLOP = 1000000
+private const val DISMISS_DELAY = 100L
+private const val RUBBERBAND_FACTOR = 0.2f
+private const val SETTINGS_BUTTON_TRANSLATION_FRACTION = 0.3f
+
+/**
+ * Default spring configuration to use for animations where stiffness and/or damping ratio
+ * were not provided, and a default spring was not set via [PhysicsAnimator.setDefaultSpringConfig].
+ */
+private val translationConfig = PhysicsAnimator.SpringConfig(
+ SpringForce.STIFFNESS_MEDIUM,
+ SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+
+/**
+ * A controller class for the media scrollview, responsible for touch handling
+ */
+class MediaCarouselScrollHandler(
+ private val scrollView: MediaScrollView,
+ private val pageIndicator: PageIndicator,
+ private val mainExecutor: DelayableExecutor,
+ private val dismissCallback: () -> Unit,
+ private var translationChangedListener: () -> Unit,
+ private val falsingManager: FalsingManager
+) {
+ /**
+ * Do we need falsing protection?
+ */
+ var falsingProtectionNeeded: Boolean = false
+ /**
+ * The width of the carousel
+ */
+ private var carouselWidth: Int = 0
+
+ /**
+ * The height of the carousel
+ */
+ private var carouselHeight: Int = 0
+
+ /**
+ * How much are we scrolled into the current media?
+ */
+ private var cornerRadius: Int = 0
+
+ /**
+ * The content where the players are added
+ */
+ private var mediaContent: ViewGroup
+ /**
+ * The gesture detector to detect touch gestures
+ */
+ private val gestureDetector: GestureDetectorCompat
+
+ /**
+ * The settings button view
+ */
+ private lateinit var settingsButton: View
+
+ /**
+ * What's the currently active player index?
+ */
+ var activeMediaIndex: Int = 0
+ private set
+ /**
+ * How much are we scrolled into the current media?
+ */
+ private var scrollIntoCurrentMedia: Int = 0
+
+ /**
+ * how much is the content translated in X
+ */
+ var contentTranslation = 0.0f
+ private set(value) {
+ field = value
+ mediaContent.translationX = value
+ updateSettingsPresentation()
+ translationChangedListener.invoke()
+ updateClipToOutline()
+ }
+
+ /**
+ * The width of a player including padding
+ */
+ var playerWidthPlusPadding: Int = 0
+ set(value) {
+ field = value
+ // The player width has changed, let's update the scroll position to make sure
+ // it's still at the same place
+ var newScroll = activeMediaIndex * playerWidthPlusPadding
+ if (scrollIntoCurrentMedia > playerWidthPlusPadding) {
+ newScroll += playerWidthPlusPadding -
+ (scrollIntoCurrentMedia - playerWidthPlusPadding)
+ } else {
+ newScroll += scrollIntoCurrentMedia
+ }
+ scrollView.scrollX = newScroll
+ }
+
+ /**
+ * Does the dismiss currently show the setting cog?
+ */
+ var showsSettingsButton: Boolean = false
+
+ /**
+ * A utility to detect gestures, used in the touch listener
+ */
+ private val gestureListener = object : GestureDetector.SimpleOnGestureListener() {
+ override fun onFling(
+ eStart: MotionEvent?,
+ eCurrent: MotionEvent?,
+ vX: Float,
+ vY: Float
+ ) = onFling(vX, vY)
+
+ override fun onScroll(
+ down: MotionEvent?,
+ lastMotion: MotionEvent?,
+ distanceX: Float,
+ distanceY: Float
+ ) = onScroll(down!!, lastMotion!!, distanceX)
+
+ override fun onDown(e: MotionEvent?): Boolean {
+ if (falsingProtectionNeeded) {
+ falsingManager.onNotificationStartDismissing()
+ }
+ return false
+ }
+ }
+
+ /**
+ * The touch listener for the scroll view
+ */
+ private val touchListener = object : Gefingerpoken {
+ override fun onTouchEvent(motionEvent: MotionEvent?) = onTouch(motionEvent!!)
+ override fun onInterceptTouchEvent(ev: MotionEvent?) = onInterceptTouch(ev!!)
+ }
+
+ /**
+ * A listener that is invoked when the scrolling changes to update player visibilities
+ */
+ private val scrollChangedListener = object : View.OnScrollChangeListener {
+ override fun onScrollChange(
+ v: View?,
+ scrollX: Int,
+ scrollY: Int,
+ oldScrollX: Int,
+ oldScrollY: Int
+ ) {
+ if (playerWidthPlusPadding == 0) {
+ return
+ }
+ onMediaScrollingChanged(scrollX / playerWidthPlusPadding,
+ scrollX % playerWidthPlusPadding)
+ }
+ }
+
+ init {
+ gestureDetector = GestureDetectorCompat(scrollView.context, gestureListener)
+ scrollView.touchListener = touchListener
+ scrollView.setOverScrollMode(View.OVER_SCROLL_NEVER)
+ mediaContent = scrollView.contentContainer
+ scrollView.setOnScrollChangeListener(scrollChangedListener)
+ scrollView.outlineProvider = object : ViewOutlineProvider() {
+ override fun getOutline(view: View?, outline: Outline?) {
+ outline?.setRoundRect(0, 0, carouselWidth, carouselHeight, cornerRadius.toFloat())
+ }
+ }
+ }
+
+ fun onSettingsButtonUpdated(button: View) {
+ settingsButton = button
+ // We don't have a context to resolve, lets use the settingsbuttons one since that is
+ // reinflated appropriately
+ cornerRadius = settingsButton.resources.getDimensionPixelSize(
+ Utils.getThemeAttr(settingsButton.context, android.R.attr.dialogCornerRadius))
+ updateSettingsPresentation()
+ scrollView.invalidateOutline()
+ }
+
+ private fun updateSettingsPresentation() {
+ if (showsSettingsButton) {
+ val settingsOffset = MathUtils.map(
+ 0.0f,
+ getMaxTranslation().toFloat(),
+ 0.0f,
+ 1.0f,
+ Math.abs(contentTranslation))
+ val settingsTranslation = (1.0f - settingsOffset) * -settingsButton.width *
+ SETTINGS_BUTTON_TRANSLATION_FRACTION
+ val newTranslationX: Float
+ if (contentTranslation > 0) {
+ newTranslationX = settingsTranslation
+ } else {
+ newTranslationX = scrollView.width - settingsTranslation - settingsButton.width
+ }
+ val rotation = (1.0f - settingsOffset) * 50
+ settingsButton.rotation = rotation * -Math.signum(contentTranslation)
+ val alpha = MathUtils.map(0.5f, 1.0f, 0.0f, 1.0f, settingsOffset)
+ settingsButton.alpha = alpha
+ settingsButton.visibility = if (alpha != 0.0f) View.VISIBLE else View.INVISIBLE
+ settingsButton.translationX = newTranslationX
+ settingsButton.translationY = (scrollView.height - settingsButton.height) / 2.0f
+ } else {
+ settingsButton.visibility = View.INVISIBLE
+ }
+ }
+
+ private fun onTouch(motionEvent: MotionEvent): Boolean {
+ val isUp = motionEvent.action == MotionEvent.ACTION_UP
+ if (isUp && falsingProtectionNeeded) {
+ falsingManager.onNotificationStopDismissing()
+ }
+ if (gestureDetector.onTouchEvent(motionEvent)) {
+ if (isUp) {
+ // If this is an up and we're flinging, we don't want to have this touch reach
+ // the view, otherwise that would scroll, while we are trying to snap to the
+ // new page. Let's dispatch a cancel instead.
+ scrollView.cancelCurrentScroll()
+ return true
+ } else {
+ // Pass touches to the scrollView
+ return false
+ }
+ }
+ if (isUp || motionEvent.action == MotionEvent.ACTION_CANCEL) {
+ // It's an up and the fling didn't take it above
+ val pos = scrollView.scrollX % playerWidthPlusPadding
+ val scollXAmount: Int
+ if (pos > playerWidthPlusPadding / 2) {
+ scollXAmount = playerWidthPlusPadding - pos
+ } else {
+ scollXAmount = -1 * pos
+ }
+ if (scollXAmount != 0) {
+ // Delay the scrolling since scrollView calls springback which cancels
+ // the animation again..
+ mainExecutor.execute {
+ scrollView.smoothScrollBy(scollXAmount, 0)
+ }
+ }
+ val currentTranslation = scrollView.getContentTranslation()
+ if (currentTranslation != 0.0f) {
+ // We started a Swipe but didn't end up with a fling. Let's either go to the
+ // dismissed position or go back.
+ val springBack = Math.abs(currentTranslation) < getMaxTranslation() / 2
+ || isFalseTouch()
+ val newTranslation: Float
+ if (springBack) {
+ newTranslation = 0.0f
+ } else {
+ newTranslation = getMaxTranslation() * Math.signum(currentTranslation)
+ if (!showsSettingsButton) {
+ // Delay the dismiss a bit to avoid too much overlap. Waiting until the
+ // animation has finished also feels a bit too slow here.
+ mainExecutor.executeDelayed({
+ dismissCallback.invoke()
+ }, DISMISS_DELAY)
+ }
+ }
+ PhysicsAnimator.getInstance(this).spring(CONTENT_TRANSLATION,
+ newTranslation, startVelocity = 0.0f, config = translationConfig).start()
+ scrollView.animationTargetX = newTranslation
+ }
+ }
+ // Always pass touches to the scrollView
+ return false
+ }
+
+ private fun isFalseTouch() = falsingProtectionNeeded && falsingManager.isFalseTouch
+
+ private fun getMaxTranslation() = if (showsSettingsButton) {
+ settingsButton.width
+ } else {
+ playerWidthPlusPadding
+ }
+
+ private fun onInterceptTouch(motionEvent: MotionEvent): Boolean {
+ return gestureDetector.onTouchEvent(motionEvent)
+ }
+
+ fun onScroll(down: MotionEvent,
+ lastMotion: MotionEvent,
+ distanceX: Float): Boolean {
+ val totalX = lastMotion.x - down.x
+ val currentTranslation = scrollView.getContentTranslation()
+ if (currentTranslation != 0.0f ||
+ !scrollView.canScrollHorizontally((-totalX).toInt())) {
+ var newTranslation = currentTranslation - distanceX
+ val absTranslation = Math.abs(newTranslation)
+ if (absTranslation > getMaxTranslation()) {
+ // Rubberband all translation above the maximum
+ if (Math.signum(distanceX) != Math.signum(currentTranslation)) {
+ // The movement is in the same direction as our translation,
+ // Let's rubberband it.
+ if (Math.abs(currentTranslation) > getMaxTranslation()) {
+ // we were already overshooting before. Let's add the distance
+ // fully rubberbanded.
+ newTranslation = currentTranslation - distanceX * RUBBERBAND_FACTOR
+ } else {
+ // We just crossed the boundary, let's rubberband it all
+ newTranslation = Math.signum(newTranslation) * (getMaxTranslation() +
+ (absTranslation - getMaxTranslation()) * RUBBERBAND_FACTOR)
+ }
+ } // Otherwise we don't have do do anything, and will remove the unrubberbanded
+ // translation
+ }
+ if (Math.signum(newTranslation) != Math.signum(currentTranslation)
+ && currentTranslation != 0.0f) {
+ // We crossed the 0.0 threshold of the translation. Let's see if we're allowed
+ // to scroll into the new direction
+ if (scrollView.canScrollHorizontally(-newTranslation.toInt())) {
+ // We can actually scroll in the direction where we want to translate,
+ // Let's make sure to stop at 0
+ newTranslation = 0.0f
+ }
+ }
+ val physicsAnimator = PhysicsAnimator.getInstance(this)
+ if (physicsAnimator.isRunning()) {
+ physicsAnimator.spring(CONTENT_TRANSLATION,
+ newTranslation, startVelocity = 0.0f, config = translationConfig).start()
+ } else {
+ contentTranslation = newTranslation
+ }
+ scrollView.animationTargetX = newTranslation
+ return true
+ }
+ return false
+ }
+
+ private fun onFling(
+ vX: Float,
+ vY: Float
+ ): Boolean {
+ if (vX * vX < 0.5 * vY * vY) {
+ return false
+ }
+ if (vX * vX < FLING_SLOP) {
+ return false
+ }
+ val currentTranslation = scrollView.getContentTranslation()
+ if (currentTranslation != 0.0f) {
+ // We're translated and flung. Let's see if the fling is in the same direction
+ val newTranslation: Float
+ if (Math.signum(vX) != Math.signum(currentTranslation) || isFalseTouch()) {
+ // The direction of the fling isn't the same as the translation, let's go to 0
+ newTranslation = 0.0f
+ } else {
+ newTranslation = getMaxTranslation() * Math.signum(currentTranslation)
+ // Delay the dismiss a bit to avoid too much overlap. Waiting until the animation
+ // has finished also feels a bit too slow here.
+ if (!showsSettingsButton) {
+ mainExecutor.executeDelayed({
+ dismissCallback.invoke()
+ }, DISMISS_DELAY)
+ }
+ }
+ PhysicsAnimator.getInstance(this).spring(CONTENT_TRANSLATION,
+ newTranslation, startVelocity = vX, config = translationConfig).start()
+ scrollView.animationTargetX = newTranslation
+ } else {
+ // We're flinging the player! Let's go either to the previous or to the next player
+ val pos = scrollView.scrollX
+ val currentIndex = if (playerWidthPlusPadding > 0) pos / playerWidthPlusPadding else 0
+ var destIndex = if (vX <= 0) currentIndex + 1 else currentIndex
+ destIndex = Math.max(0, destIndex)
+ destIndex = Math.min(mediaContent.getChildCount() - 1, destIndex)
+ val view = mediaContent.getChildAt(destIndex)
+ // We need to post this since we're dispatching a touch to the underlying view to cancel
+ // but canceling will actually abort the animation.
+ mainExecutor.execute {
+ scrollView.smoothScrollTo(view.left, scrollView.scrollY)
+ }
+ }
+ return true
+ }
+
+ /**
+ * Reset the translation of the players when swiped
+ */
+ fun resetTranslation(animate: Boolean = false) {
+ if (scrollView.getContentTranslation() != 0.0f) {
+ if (animate) {
+ PhysicsAnimator.getInstance(this).spring(CONTENT_TRANSLATION,
+ 0.0f, config = translationConfig).start()
+ scrollView.animationTargetX = 0.0f
+ } else {
+ PhysicsAnimator.getInstance(this).cancel()
+ contentTranslation = 0.0f
+ }
+ }
+ }
+
+ private fun updateClipToOutline() {
+ val clip = contentTranslation != 0.0f || scrollIntoCurrentMedia != 0
+ scrollView.clipToOutline = clip
+ }
+
+ private fun onMediaScrollingChanged(newIndex: Int, scrollInAmount: Int) {
+ val wasScrolledIn = scrollIntoCurrentMedia != 0
+ scrollIntoCurrentMedia = scrollInAmount
+ val nowScrolledIn = scrollIntoCurrentMedia != 0
+ if (newIndex != activeMediaIndex || wasScrolledIn != nowScrolledIn) {
+ activeMediaIndex = newIndex
+ updatePlayerVisibilities()
+ }
+ val location = activeMediaIndex.toFloat() + if (playerWidthPlusPadding > 0)
+ scrollInAmount.toFloat() / playerWidthPlusPadding else 0f
+ pageIndicator.setLocation(location)
+ updateClipToOutline()
+ }
+
+ /**
+ * Notified whenever the players or their order has changed
+ */
+ fun onPlayersChanged() {
+ updatePlayerVisibilities()
+ updateMediaPaddings()
+ }
+
+ private fun updateMediaPaddings() {
+ val padding = scrollView.context.resources.getDimensionPixelSize(R.dimen.qs_media_padding)
+ val childCount = mediaContent.childCount
+ for (i in 0 until childCount) {
+ val mediaView = mediaContent.getChildAt(i)
+ val desiredPaddingEnd = if (i == childCount - 1) 0 else padding
+ val layoutParams = mediaView.layoutParams as ViewGroup.MarginLayoutParams
+ if (layoutParams.marginEnd != desiredPaddingEnd) {
+ layoutParams.marginEnd = desiredPaddingEnd
+ mediaView.layoutParams = layoutParams
+ }
+ }
+ }
+
+ private fun updatePlayerVisibilities() {
+ val scrolledIn = scrollIntoCurrentMedia != 0
+ for (i in 0 until mediaContent.childCount) {
+ val view = mediaContent.getChildAt(i)
+ val visible = (i == activeMediaIndex) || ((i == (activeMediaIndex + 1)) && scrolledIn)
+ view.visibility = if (visible) View.VISIBLE else View.INVISIBLE
+ }
+ }
+
+ /**
+ * Notify that a player will be removed right away. This gives us the opporunity to look
+ * where it was and update our scroll position.
+ */
+ fun onPrePlayerRemoved(removed: MediaControlPanel) {
+ val beforeActive = mediaContent.indexOfChild(removed.view?.player) <= activeMediaIndex
+ 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)
+ scrollView.scrollX = Math.max(scrollView.scrollX -
+ playerWidthPlusPadding, 0)
+ }
+ }
+
+ /**
+ * Update the bounds of the carousel
+ */
+ fun setCarouselBounds(currentCarouselWidth: Int, currentCarouselHeight: Int) {
+ if (currentCarouselHeight != carouselHeight || currentCarouselWidth != carouselHeight) {
+ carouselWidth = currentCarouselWidth
+ carouselHeight = currentCarouselHeight
+ scrollView.invalidateOutline()
+ }
+ }
+
+ companion object {
+ private val CONTENT_TRANSLATION = object : FloatPropertyCompat<MediaCarouselScrollHandler>(
+ "contentTranslation") {
+ override fun getValue(handler: MediaCarouselScrollHandler): Float {
+ return handler.contentTranslation
+ }
+
+ override fun setValue(handler: MediaCarouselScrollHandler, value: Float) {
+ handler.contentTranslation = value
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index c80c82f61fc6..3fc162ead6d1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -20,13 +20,10 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
-import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.Icon;
-import android.graphics.drawable.RippleDrawable;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
@@ -60,6 +57,7 @@ import javax.inject.Inject;
*/
public class MediaControlPanel {
private static final String TAG = "MediaControlPanel";
+ private static final float DISABLED_ALPHA = 0.38f;
// Button IDs for QS controls
static final int[] ACTION_IDS = {
@@ -258,12 +256,6 @@ public class MediaControlPanel {
ImageView iconView = mViewHolder.getSeamlessIcon();
TextView deviceName = mViewHolder.getSeamlessText();
- // Update the outline color
- RippleDrawable bkgDrawable = (RippleDrawable) mViewHolder.getSeamless().getForeground();
- GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
- rect.setStroke(2, deviceName.getCurrentTextColor());
- rect.setColor(Color.TRANSPARENT);
-
final MediaDeviceData device = data.getDevice();
final int seamlessId = mViewHolder.getSeamless().getId();
final int seamlessFallbackId = mViewHolder.getSeamlessFallback().getId();
@@ -276,6 +268,11 @@ public class MediaControlPanel {
mViewHolder.getSeamless().setVisibility(seamlessVisibility);
expandedSet.setVisibility(seamlessId, seamlessVisibility);
collapsedSet.setVisibility(seamlessId, seamlessVisibility);
+ final float seamlessAlpha = data.getResumption() ? DISABLED_ALPHA : 1.0f;
+ expandedSet.setAlpha(seamlessId, seamlessAlpha);
+ collapsedSet.setAlpha(seamlessId, seamlessAlpha);
+ // Disable clicking on output switcher for resumption controls.
+ mViewHolder.getSeamless().setEnabled(!data.getResumption());
if (showFallback) {
iconView.setImageDrawable(null);
deviceName.setText(null);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
index 0b0ffcede3af..8c9cb1b240bf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -81,6 +81,11 @@ data class MediaData(
*/
var resumeAction: Runnable?,
/**
+ * Indicates that this player is a resumption player (ie. It only shows a play actions which
+ * will start the app and start playing).
+ */
+ var resumption: Boolean = false,
+ /**
* Notification key for cancelling a media player after a timeout (when not using resumption.)
*/
val notificationKey: String? = null,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index c59a548c8db4..5052386e65e1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -323,7 +323,7 @@ class MediaDataManager(
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, notificationKey = packageName,
+ resumeAction = resumeAction, resumption = true, notificationKey = packageName,
hasCheckedForResume = true))
}
}
@@ -432,12 +432,13 @@ class MediaDataManager(
}
}
- val resumeAction: Runnable? = mediaEntries.get(key)?.resumeAction
- val hasCheckedForResume = mediaEntries.get(key)?.hasCheckedForResume == true
foregroundExecutor.execute {
+ val resumeAction: Runnable? = mediaEntries[key]?.resumeAction
+ val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true
+ val active = mediaEntries[key]?.active ?: true
onMediaDataLoaded(key, oldKey, MediaData(true, bgColor, app, smallIconDrawable, artist,
song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token,
- notif.contentIntent, null, active = true, resumeAction = resumeAction,
+ notif.contentIntent, null, active, resumeAction = resumeAction,
notificationKey = key, hasCheckedForResume = hasCheckedForResume))
}
}
@@ -542,7 +543,7 @@ class MediaDataManager(
val data = mediaEntries.remove(key)!!
val resumeAction = getResumeMediaAction(data.resumeAction!!)
val updated = data.copy(token = null, actions = listOf(resumeAction),
- actionsToShowInCompact = listOf(0), active = false)
+ actionsToShowInCompact = listOf(0), active = false, resumption = true)
mediaEntries.put(data.packageName, updated)
// Notify listeners of "new" controls
val listenersCopy = listeners.toSet()
@@ -592,6 +593,16 @@ class MediaDataManager(
}
}
+ /**
+ * Invoked when the user has dismissed the media carousel
+ */
+ fun onSwipeToDismiss() {
+ val mediaKeys = mediaEntries.keys.toSet()
+ mediaKeys.forEach {
+ setTimedOut(it, timedOut = true)
+ }
+ }
+
interface Listener {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index 26fa29613dc4..c41e6104833e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -49,7 +49,7 @@ class MediaHierarchyManager @Inject constructor(
private val statusBarStateController: SysuiStatusBarStateController,
private val keyguardStateController: KeyguardStateController,
private val bypassController: KeyguardBypassController,
- private val mediaViewManager: MediaViewManager,
+ private val mediaCarouselController: MediaCarouselController,
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
wakefulnessLifecycle: WakefulnessLifecycle
) {
@@ -65,7 +65,7 @@ class MediaHierarchyManager @Inject constructor(
private var animationStartBounds: Rect = Rect()
private var targetBounds: Rect = Rect()
private val mediaFrame
- get() = mediaViewManager.mediaFrame
+ get() = mediaCarouselController.mediaFrame
private var statusbarState: Int = statusBarStateController.state
private var animator = ValueAnimator.ofFloat(0.0f, 1.0f).apply {
interpolator = Interpolators.FAST_OUT_SLOW_IN
@@ -140,6 +140,18 @@ class MediaHierarchyManager @Inject constructor(
}
/**
+ * Is the shade currently collapsing from the expanded qs? If we're on the lockscreen and in qs,
+ * we wouldn't want to transition in that case.
+ */
+ var collapsingShadeFromQS: Boolean = false
+ set(value) {
+ if (field != value) {
+ field = value
+ updateDesiredLocation(forceNoAnimation = true)
+ }
+ }
+
+ /**
* Are location changes currently blocked?
*/
private val blockLocationChanges: Boolean
@@ -161,6 +173,19 @@ class MediaHierarchyManager @Inject constructor(
}
/**
+ * Are we currently fullyAwake
+ */
+ private var fullyAwake: Boolean = false
+ set(value) {
+ if (field != value) {
+ field = value
+ if (value) {
+ updateDesiredLocation(forceNoAnimation = true)
+ }
+ }
+ }
+
+ /**
* Is the doze animation currently Running
*/
private var dozeAnimationRunning: Boolean = false
@@ -206,10 +231,12 @@ class MediaHierarchyManager @Inject constructor(
override fun onStartedGoingToSleep() {
goingToSleep = true
+ fullyAwake = false
}
override fun onFinishedWakingUp() {
goingToSleep = false
+ fullyAwake = true
}
override fun onStartedWakingUp() {
@@ -227,6 +254,10 @@ class MediaHierarchyManager @Inject constructor(
fun register(mediaObject: MediaHost): UniqueObjectHostView {
val viewHost = createUniqueObjectHost()
mediaObject.hostView = viewHost
+ mediaObject.addVisibilityChangeListener {
+ // Never animate because of a visibility change, only state changes should do that
+ updateDesiredLocation(forceNoAnimation = true)
+ }
mediaHosts[mediaObject.location] = mediaObject
if (mediaObject.location == desiredLocation) {
// In case we are overriding a view that is already visible, make sure we attach it
@@ -260,8 +291,10 @@ class MediaHierarchyManager @Inject constructor(
/**
* Updates the location that the view should be in. If it changes, an animation may be triggered
* going from the old desired location to the new one.
+ *
+ * @param forceNoAnimation optional parameter telling the system not to animate
*/
- private fun updateDesiredLocation() {
+ private fun updateDesiredLocation(forceNoAnimation: Boolean = false) {
val desiredLocation = calculateLocation()
if (desiredLocation != this.desiredLocation) {
if (this.desiredLocation >= 0) {
@@ -270,11 +303,12 @@ class MediaHierarchyManager @Inject constructor(
val isNewView = this.desiredLocation == -1
this.desiredLocation = desiredLocation
// Let's perform a transition
- val animate = shouldAnimateTransition(desiredLocation, previousLocation)
+ val animate = !forceNoAnimation &&
+ shouldAnimateTransition(desiredLocation, previousLocation)
val (animDuration, delay) = getAnimationParams(previousLocation, desiredLocation)
val host = getHost(desiredLocation)
- mediaViewManager.onDesiredLocationChanged(desiredLocation, host, animate, animDuration,
- delay)
+ mediaCarouselController.onDesiredLocationChanged(desiredLocation, host, animate,
+ animDuration, delay)
performTransitionToNewLocation(isNewView, animate)
}
}
@@ -457,7 +491,7 @@ class MediaHierarchyManager @Inject constructor(
val startLocation = if (currentlyInGuidedTransformation) previousLocation else -1
val progress = if (currentlyInGuidedTransformation) getTransformationProgress() else 1.0f
val endLocation = desiredLocation
- mediaViewManager.setCurrentState(startLocation, endLocation, progress, immediately)
+ mediaCarouselController.setCurrentState(startLocation, endLocation, progress, immediately)
updateHostAttachment()
if (currentAttachmentLocation == IN_OVERLAY) {
mediaFrame.setLeftTopRightBottom(
@@ -524,6 +558,18 @@ class MediaHierarchyManager @Inject constructor(
!statusBarStateController.isDozing) {
return LOCATION_QS
}
+ if (location == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QS &&
+ collapsingShadeFromQS) {
+ // When collapsing on the lockscreen, we want to remain in QS
+ return LOCATION_QS
+ }
+ if (location != LOCATION_LOCKSCREEN && desiredLocation == LOCATION_LOCKSCREEN
+ && !fullyAwake) {
+ // When unlocking from dozing / while waking up, the media shouldn't be transitioning
+ // in an animated way. Let's keep it in the lockscreen until we're fully awake and
+ // reattach it without an animation
+ return LOCATION_LOCKSCREEN
+ }
return location
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
index 7c5f0d1c2a16..1ae9d3ff4ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
@@ -2,6 +2,7 @@ package com.android.systemui.media
import android.graphics.PointF
import android.graphics.Rect
+import android.util.ArraySet
import android.view.View
import android.view.View.OnAttachStateChangeListener
import com.android.systemui.util.animation.MeasurementInput
@@ -20,7 +21,7 @@ class MediaHost @Inject constructor(
lateinit var hostView: UniqueObjectHostView
var location: Int = -1
private set
- var visibleChangedListener: ((Boolean) -> Unit)? = null
+ private var visibleChangedListeners: ArraySet<(Boolean) -> Unit> = ArraySet()
private val tmpLocationOnScreen: IntArray = intArrayOf(0, 0)
@@ -58,6 +59,10 @@ class MediaHost @Inject constructor(
}
}
+ fun addVisibilityChangeListener(listener: (Boolean) -> Unit) {
+ visibleChangedListeners.add(listener)
+ }
+
/**
* Initialize this MediaObject and create a host view.
* All state should already be set on this host before calling this method in order to avoid
@@ -113,8 +118,13 @@ class MediaHost @Inject constructor(
} else {
mediaDataManager.hasAnyMedia()
}
- hostView.visibility = if (visible) View.VISIBLE else View.GONE
- visibleChangedListener?.invoke(visible)
+ val newVisibility = if (visible) View.VISIBLE else View.GONE
+ if (newVisibility != hostView.visibility) {
+ hostView.visibility = newVisibility
+ visibleChangedListeners.forEach {
+ it.invoke(visible)
+ }
+ }
}
class MediaHostStateHolder @Inject constructor() : MediaHostState {
@@ -153,6 +163,15 @@ class MediaHost @Inject constructor(
changedListener?.invoke()
}
+ override var falsingProtectionNeeded: Boolean = false
+ set(value) {
+ if (field == value) {
+ return
+ }
+ field = value
+ changedListener?.invoke()
+ }
+
override fun getPivotX(): Float = gonePivot.x
override fun getPivotY(): Float = gonePivot.y
override fun setGonePivot(x: Float, y: Float) {
@@ -178,6 +197,7 @@ class MediaHost @Inject constructor(
mediaHostState.measurementInput = measurementInput?.copy()
mediaHostState.visible = visible
mediaHostState.gonePivot.set(gonePivot)
+ mediaHostState.falsingProtectionNeeded = falsingProtectionNeeded
return mediaHostState
}
@@ -197,6 +217,9 @@ class MediaHost @Inject constructor(
if (visible != other.visible) {
return false
}
+ if (falsingProtectionNeeded != other.falsingProtectionNeeded) {
+ return false
+ }
if (!gonePivot.equals(other.getPivotX(), other.getPivotY())) {
return false
}
@@ -206,6 +229,7 @@ class MediaHost @Inject constructor(
override fun hashCode(): Int {
var result = measurementInput?.hashCode() ?: 0
result = 31 * result + expansion.hashCode()
+ result = 31 * result + falsingProtectionNeeded.hashCode()
result = 31 * result + showsOnlyActiveMedia.hashCode()
result = 31 * result + if (visible) 1 else 2
result = 31 * result + gonePivot.hashCode()
@@ -239,6 +263,11 @@ interface MediaHostState {
var visible: Boolean
/**
+ * Does this host need any falsing protection?
+ */
+ var falsingProtectionNeeded: Boolean
+
+ /**
* Sets the pivot point when clipping the height or width.
* Clipping happens when animating visibility when we're visible in QS but not on QQS,
* for example.
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaScrollView.kt b/packages/SystemUI/src/com/android/systemui/media/MediaScrollView.kt
new file mode 100644
index 000000000000..a079b06a0b10
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaScrollView.kt
@@ -0,0 +1,100 @@
+package com.android.systemui.media
+
+import android.content.Context
+import android.os.SystemClock
+import android.util.AttributeSet
+import android.view.InputDevice
+import android.view.MotionEvent
+import android.view.ViewGroup
+import android.widget.HorizontalScrollView
+import com.android.systemui.Gefingerpoken
+import com.android.systemui.util.animation.physicsAnimator
+
+/**
+ * A ScrollView used in Media that doesn't limit itself to the childs bounds. This is useful
+ * when only measuring children but not the parent, when trying to apply a new scroll position
+ */
+class MediaScrollView @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
+ : HorizontalScrollView(context, attrs, defStyleAttr) {
+
+ lateinit var contentContainer: ViewGroup
+ private set
+ var touchListener: Gefingerpoken? = null
+
+ /**
+ * The target value of the translation X animation. Only valid if the physicsAnimator is running
+ */
+ var animationTargetX = 0.0f
+
+ /**
+ * Get the current content translation. This is usually the normal translationX of the content,
+ * but when animating, it might differ
+ */
+ fun getContentTranslation() = if (contentContainer.physicsAnimator.isRunning()) {
+ animationTargetX
+ } else {
+ contentContainer.translationX
+ }
+
+ /**
+ * Allow all scrolls to go through, use base implementation
+ */
+ override fun scrollTo(x: Int, y: Int) {
+ if (mScrollX != x || mScrollY != y) {
+ val oldX: Int = mScrollX
+ val oldY: Int = mScrollY
+ mScrollX = x
+ mScrollY = y
+ invalidateParentCaches()
+ onScrollChanged(mScrollX, mScrollY, oldX, oldY)
+ if (!awakenScrollBars()) {
+ postInvalidateOnAnimation()
+ }
+ }
+ }
+
+ override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
+ var intercept = false;
+ touchListener?.let {
+ intercept = it.onInterceptTouchEvent(ev)
+ }
+ return super.onInterceptTouchEvent(ev) || intercept;
+ }
+
+ override fun onTouchEvent(ev: MotionEvent?): Boolean {
+ var touch = false;
+ touchListener?.let {
+ touch = it.onTouchEvent(ev)
+ }
+ return super.onTouchEvent(ev) || touch
+ }
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ contentContainer = getChildAt(0) as ViewGroup
+ }
+
+ override fun overScrollBy(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int,
+ scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int,
+ maxOverScrollY: Int, isTouchEvent: Boolean): Boolean {
+ if (getContentTranslation() != 0.0f) {
+ // When we're dismissing we ignore all the scrolling
+ return false
+ }
+ return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
+ scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent)
+ }
+
+ /**
+ * Cancel the current touch event going on.
+ */
+ fun cancelCurrentScroll() {
+ val now = SystemClock.uptimeMillis()
+ val event = MotionEvent.obtain(now, now,
+ MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0)
+ event.source = InputDevice.SOURCE_TOUCHSCREEN
+ super.onTouchEvent(event)
+ event.recycle()
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
index cf8a636a2b67..9a134dbe0264 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
@@ -71,6 +71,7 @@ class MediaTimeoutListener @Inject constructor(
) : MediaController.Callback() {
var timedOut = false
+ private var playing: Boolean? = null
// Resume controls may have null token
private val mediaController = if (data.token != null) {
@@ -94,7 +95,13 @@ class MediaTimeoutListener @Inject constructor(
Log.v(TAG, "onPlaybackStateChanged: $state")
}
- if (state == null || !isPlayingState(state.state)) {
+ val isPlaying = state != null && isPlayingState(state.state)
+ if (playing == isPlaying && playing != null) {
+ return
+ }
+ playing = isPlaying
+
+ if (!isPlaying) {
if (DEBUG) {
Log.v(TAG, "schedule timeout for $key")
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
index 90ccfc6ca725..fc22c026974a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
@@ -17,9 +17,11 @@
package com.android.systemui.media
import android.content.Context
+import android.content.res.Configuration
import android.graphics.PointF
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.R
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.animation.MeasurementOutput
import com.android.systemui.util.animation.TransitionLayout
import com.android.systemui.util.animation.TransitionLayoutController
@@ -32,9 +34,14 @@ import javax.inject.Inject
*/
class MediaViewController @Inject constructor(
context: Context,
+ private val configurationController: ConfigurationController,
private val mediaHostStatesManager: MediaHostStatesManager
) {
+ /**
+ * A listener when the current dimensions of the player change
+ */
+ lateinit var sizeChangedListener: () -> Unit
private var firstRefresh: Boolean = true
private var transitionLayout: TransitionLayout? = null
private val layoutController = TransitionLayoutController()
@@ -52,12 +59,14 @@ class MediaViewController @Inject constructor(
* The ending location of the view where it ends when all animations and transitions have
* finished
*/
+ @MediaLocation
private var currentEndLocation: Int = -1
/**
* The ending location of the view where it ends when all animations and transitions have
* finished
*/
+ @MediaLocation
private var currentStartLocation: Int = -1
/**
@@ -76,10 +85,42 @@ class MediaViewController @Inject constructor(
private val tmpPoint = PointF()
/**
+ * The current width of the player. This might not factor in case the player is animating
+ * to the current state, but represents the end state
+ */
+ var currentWidth: Int = 0
+ /**
+ * The current height of the player. This might not factor in case the player is animating
+ * to the current state, but represents the end state
+ */
+ var currentHeight: Int = 0
+
+ /**
+ * A callback for RTL config changes
+ */
+ private val configurationListener = object : ConfigurationController.ConfigurationListener {
+ override fun onConfigChanged(newConfig: Configuration?) {
+ // Because the TransitionLayout is not always attached (and calculates/caches layout
+ // results regardless of attach state), we have to force the layoutDirection of the view
+ // to the correct value for the user's current locale to ensure correct recalculation
+ // when/after calling refreshState()
+ newConfig?.apply {
+ if (transitionLayout?.rawLayoutDirection != layoutDirection) {
+ transitionLayout?.layoutDirection = layoutDirection
+ refreshState()
+ }
+ }
+ }
+ }
+
+ /**
* A callback for media state changes
*/
val stateCallback = object : MediaHostStatesManager.Callback {
- override fun onHostStateChanged(location: Int, mediaHostState: MediaHostState) {
+ override fun onHostStateChanged(
+ @MediaLocation location: Int,
+ mediaHostState: MediaHostState
+ ) {
if (location == currentEndLocation || location == currentStartLocation) {
setCurrentState(currentStartLocation,
currentEndLocation,
@@ -105,6 +146,12 @@ class MediaViewController @Inject constructor(
collapsedLayout.load(context, R.xml.media_collapsed)
expandedLayout.load(context, R.xml.media_expanded)
mediaHostStatesManager.addController(this)
+ layoutController.sizeChangedListener = { width: Int, height: Int ->
+ currentWidth = width
+ currentHeight = height
+ sizeChangedListener.invoke()
+ }
+ configurationController.addCallback(configurationListener)
}
/**
@@ -112,6 +159,7 @@ class MediaViewController @Inject constructor(
*/
fun onDestroy() {
mediaHostStatesManager.removeController(this)
+ configurationController.removeCallback(configurationListener)
}
private fun ensureAllMeasurements() {
@@ -279,6 +327,8 @@ class MediaViewController @Inject constructor(
tmpPoint, tmpState)
tmpState
}
+ currentWidth = result.width
+ currentHeight = result.height
layoutController.setState(result, applyImmediately, shouldAnimate, animationDuration,
animationDelay)
}
@@ -324,7 +374,7 @@ class MediaViewController @Inject constructor(
// Let's clear all of our measurements and recreate them!
viewStates.clear()
setCurrentState(currentStartLocation, currentEndLocation, currentTransitionProgress,
- applyImmediately = false)
+ applyImmediately = true)
}
firstRefresh = false
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
index 9ede083fa9ac..600fdc27ef89 100644
--- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -48,6 +48,7 @@ class PlayerViewHolder private constructor(itemView: View) {
// Seek bar
val seekBar = itemView.requireViewById<SeekBar>(R.id.media_progress_bar)
+ val progressTimes = itemView.requireViewById<ViewGroup>(R.id.notification_media_progress_time)
val elapsedTimeView = itemView.requireViewById<TextView>(R.id.media_elapsed_time)
val totalTimeView = itemView.requireViewById<TextView>(R.id.media_total_time)
@@ -93,8 +94,16 @@ class PlayerViewHolder private constructor(itemView: View) {
* @param parent Parent of inflated view.
*/
@JvmStatic fun create(inflater: LayoutInflater, parent: ViewGroup): PlayerViewHolder {
- val v = inflater.inflate(R.layout.media_view, parent, false)
- return PlayerViewHolder(v)
+ val mediaView = inflater.inflate(R.layout.media_view, parent, false)
+ // Because this media view (a TransitionLayout) is used to measure and layout the views
+ // in various states before being attached to its parent, we can't depend on the default
+ // LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
+ mediaView.layoutDirection = View.LAYOUT_DIRECTION_LOCALE
+ return PlayerViewHolder(mediaView).apply {
+ // Media playback is in the direction of tape, not time, so it stays LTR
+ seekBar.layoutDirection = View.LAYOUT_DIRECTION_LTR
+ progressTimes.layoutDirection = View.LAYOUT_DIRECTION_LTR
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
index cd8ed265bd53..c2631c923e45 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
@@ -19,6 +19,7 @@ package com.android.systemui.media
import android.text.format.DateUtils
import androidx.annotation.UiThread
import androidx.lifecycle.Observer
+import com.android.systemui.R
/**
* Observer for changes from SeekBarViewModel.
@@ -27,10 +28,18 @@ import androidx.lifecycle.Observer
*/
class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarViewModel.Progress> {
+ val seekBarDefaultMaxHeight = holder.seekBar.context.resources
+ .getDimensionPixelSize(R.dimen.qs_media_enabled_seekbar_height)
+ val seekBarDisabledHeight = holder.seekBar.context.resources
+ .getDimensionPixelSize(R.dimen.qs_media_disabled_seekbar_height)
+
/** Updates seek bar views when the data model changes. */
@UiThread
override fun onChanged(data: SeekBarViewModel.Progress) {
if (!data.enabled) {
+ if (holder.seekBar.maxHeight != seekBarDisabledHeight) {
+ holder.seekBar.maxHeight = seekBarDisabledHeight
+ }
holder.seekBar.setEnabled(false)
holder.seekBar.getThumb().setAlpha(0)
holder.seekBar.setProgress(0)
@@ -42,6 +51,10 @@ class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarVi
holder.seekBar.getThumb().setAlpha(if (data.seekAvailable) 255 else 0)
holder.seekBar.setEnabled(data.seekAvailable)
+ if (holder.seekBar.maxHeight != seekBarDefaultMaxHeight) {
+ holder.seekBar.maxHeight = seekBarDefaultMaxHeight
+ }
+
data.elapsedTime?.let {
holder.seekBar.setProgress(it)
holder.elapsedTimeView.setText(DateUtils.formatElapsedTime(
diff --git a/packages/SystemUI/src/com/android/systemui/media/UnboundHorizontalScrollView.kt b/packages/SystemUI/src/com/android/systemui/media/UnboundHorizontalScrollView.kt
deleted file mode 100644
index 8efc9549068a..000000000000
--- a/packages/SystemUI/src/com/android/systemui/media/UnboundHorizontalScrollView.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.android.systemui.media
-
-import android.content.Context
-import android.util.AttributeSet
-import android.widget.HorizontalScrollView
-
-/**
- * A Horizontal scrollview that doesn't limit itself to the childs bounds. This is useful
- * when only measuring children but not the parent, when trying to apply a new scroll position
- */
-class UnboundHorizontalScrollView @JvmOverloads constructor(
- context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
- : HorizontalScrollView(context, attrs, defStyleAttr) {
-
- /**
- * Allow all scrolls to go through, use base implementation
- */
- override fun scrollTo(x: Int, y: Int) {
- if (mScrollX != x || mScrollY != y) {
- val oldX: Int = mScrollX
- val oldY: Int = mScrollY
- mScrollX = x
- mScrollY = y
- invalidateParentCaches()
- onScrollChanged(mScrollX, mScrollY, oldX, oldY)
- if (!awakenScrollBars()) {
- postInvalidateOnAnimation()
- }
- }
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index d92434678357..e2feb71735ff 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -273,8 +273,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
sendOnPipTransitionStarted(direction);
// Don't bother doing an animation if the display rotation differs or if it's in
// a non-supported windowing mode
- wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
- wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+ applyWindowingModeChangeOnExit(wct, direction);
WindowOrganizer.applyTransaction(wct);
// Send finished callback though animation is ignored.
sendOnPipTransitionFinished(direction);
@@ -303,6 +302,16 @@ public class PipTaskOrganizer extends TaskOrganizer implements
mExitingPip = true;
}
+ private void applyWindowingModeChangeOnExit(WindowContainerTransaction wct, int direction) {
+ // 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 */);
+ }
+ }
+
/**
* Removes PiP immediately.
*/
@@ -745,13 +754,7 @@ 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;
- // 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 */);
- }
+ applyWindowingModeChangeOnExit(wct, direction);
} else {
// Just a resize in PIP
taskBounds = destinationBounds;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java b/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java
index aa17c4aa79b1..309b32fc85d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java
@@ -46,6 +46,11 @@ public class NonInterceptingScrollView extends ScrollView {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
+ } else if (!canScrollVertically(-1)) {
+ // Don't pass on the touch to the view, because scrolling will unconditionally
+ // disallow interception even if we can't scroll.
+ // if a user can't scroll at all, we should never listen to the touch.
+ return false;
}
break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index bc8f5a8fb652..e66b33c660d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -18,7 +18,6 @@ import android.util.Log;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnLayoutChangeListener;
-import android.widget.ScrollView;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.qs.QS;
@@ -300,10 +299,16 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
if (mQsPanel.getSecurityFooter() != null) {
builder.addFloat(mQsPanel.getSecurityFooter().getView(), "alpha", 0, 1);
}
+ if (mQsPanel.getDivider() != null) {
+ builder.addFloat(mQsPanel.getDivider(), "alpha", 0, 1);
+ }
mFirstPageDelayedAnimator = builder.build();
if (mQsPanel.getSecurityFooter() != null) {
mAllViews.add(mQsPanel.getSecurityFooter().getView());
}
+ if (mQsPanel.getDivider() != null) {
+ mAllViews.add(mQsPanel.getDivider());
+ }
float px = 0;
float py = 1;
if (tiles.size() <= 3) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 0332bc3e0618..6b12e478f627 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -26,8 +26,12 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
+import androidx.dynamicanimation.animation.SpringForce;
+
import com.android.systemui.R;
import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.util.animation.PhysicsAnimator;
/**
* Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
@@ -35,7 +39,22 @@ import com.android.systemui.qs.customize.QSCustomizer;
public class QSContainerImpl extends FrameLayout {
private final Point mSizePoint = new Point();
+ private static final FloatPropertyCompat<QSContainerImpl> BACKGROUND_BOTTOM =
+ new FloatPropertyCompat<QSContainerImpl>("backgroundBottom") {
+ @Override
+ public float getValue(QSContainerImpl qsImpl) {
+ return qsImpl.getBackgroundBottom();
+ }
+ @Override
+ public void setValue(QSContainerImpl background, float value) {
+ background.setBackgroundBottom((int) value);
+ }
+ };
+ private static final PhysicsAnimator.SpringConfig BACKGROUND_SPRING
+ = new PhysicsAnimator.SpringConfig(SpringForce.STIFFNESS_MEDIUM,
+ SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+ private int mBackgroundBottom = -1;
private int mHeightOverride = -1;
private QSPanel mQSPanel;
private View mQSDetail;
@@ -53,6 +72,7 @@ public class QSContainerImpl extends FrameLayout {
private boolean mQsDisabled;
private int mContentPaddingStart = -1;
private int mContentPaddingEnd = -1;
+ private boolean mAnimateBottomOnNextLayout;
public QSContainerImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -71,10 +91,30 @@ public class QSContainerImpl extends FrameLayout {
mStatusBarBackground = findViewById(R.id.quick_settings_status_bar_background);
mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view);
updateResources();
+ mHeader.getHeaderQsPanel().setMediaVisibilityChangedListener((visible) -> {
+ if (mHeader.getHeaderQsPanel().isShown()) {
+ mAnimateBottomOnNextLayout = true;
+ }
+ });
+
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
+ private void setBackgroundBottom(int value) {
+ // We're saving the bottom separately since otherwise the bottom would be overridden in
+ // the layout and the animation wouldn't properly start at the old position.
+ mBackgroundBottom = value;
+ mBackground.setBottom(value);
+ }
+
+ private float getBackgroundBottom() {
+ if (mBackgroundBottom == -1) {
+ return mBackground.getBottom();
+ }
+ return mBackgroundBottom;
+ }
+
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -140,7 +180,8 @@ public class QSContainerImpl extends FrameLayout {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- updateExpansion();
+ updateExpansion(mAnimateBottomOnNextLayout /* animate */);
+ mAnimateBottomOnNextLayout = false;
}
public void disable(int state1, int state2, boolean animate) {
@@ -181,13 +222,31 @@ public class QSContainerImpl extends FrameLayout {
}
public void updateExpansion() {
+ updateExpansion(false /* animate */);
+ }
+
+ public void updateExpansion(boolean animate) {
int height = calculateContainerHeight();
setBottom(getTop() + height);
mQSDetail.setBottom(getTop() + height);
// Pin the drag handle to the bottom of the panel.
mDragHandle.setTranslationY(height - mDragHandle.getHeight());
mBackground.setTop(mQSPanelContainer.getTop());
- mBackground.setBottom(height);
+ updateBackgroundBottom(height, animate);
+ }
+
+ private void updateBackgroundBottom(int height, boolean animated) {
+ PhysicsAnimator<QSContainerImpl> physicsAnimator = PhysicsAnimator.getInstance(this);
+ if (physicsAnimator.isPropertyAnimating(BACKGROUND_BOTTOM) || animated) {
+ // An animation is running or we want to animate
+ // Let's make sure to set the currentValue again, since the call below might only
+ // start in the next frame and otherwise we'd flicker
+ BACKGROUND_BOTTOM.setValue(this, BACKGROUND_BOTTOM.getValue(this));
+ physicsAnimator.spring(BACKGROUND_BOTTOM, height, BACKGROUND_SPRING).start();
+ } else {
+ BACKGROUND_BOTTOM.setValue(this, height);
+ }
+
}
protected int calculateContainerHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index ee3b499edfb7..2be8a9704e1c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -25,13 +25,10 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.drawable.Animatable;
import android.util.AttributeSet;
-import android.util.Pair;
import android.util.SparseArray;
-import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
-import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -46,7 +43,6 @@ import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.StatusBarWindowView;
public class QSDetail extends LinearLayout {
@@ -283,32 +279,6 @@ public class QSDetail extends LinearLayout {
}
}
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- DisplayCutout cutout = insets.getDisplayCutout();
-
- Pair<Integer, Integer> padding = StatusBarWindowView.cornerCutoutMargins(
- cutout, getDisplay());
-
- if (padding == null) {
- mQsDetailHeader.setPaddingRelative(
- getResources().getDimensionPixelSize(R.dimen.qs_detail_header_padding),
- getPaddingTop(),
- getResources().getDimensionPixelSize(R.dimen.qs_detail_header_padding),
- getPaddingBottom()
- );
- } else {
- mQsDetailHeader.setPadding(
- padding.first,
- getPaddingTop(),
- padding.second,
- getPaddingBottom()
- );
- }
-
- return super.onApplyWindowInsets(insets);
- }
-
private void handleToggleStateChanged(boolean state, boolean toggleEnabled) {
mSwitchState = state;
if (mAnimatingOpen) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 5021e0019d57..c8a34f010ae4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -65,6 +65,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.inject.Inject;
@@ -117,6 +118,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
@Nullable
protected View mFooter;
+ @Nullable
+ protected View mDivider;
@Nullable
private ViewGroup mHeaderContainer;
@@ -141,6 +144,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
private int mLastOrientation = -1;
private int mMediaTotalBottomMargin;
private int mFooterMarginStartHorizontal;
+ private Consumer<Boolean> mMediaVisibilityChangedListener;
@Inject
@@ -158,8 +162,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mMediaTotalBottomMargin = getResources().getDimensionPixelSize(
R.dimen.quick_settings_bottom_margin_media);
mMediaHost = mediaHost;
- mMediaHost.setVisibleChangedListener((visible) -> {
- switchTileLayout();
+ mMediaHost.addVisibilityChangeListener((visible) -> {
+ onMediaVisibilityChanged(visible);
return null;
});
mContext = context;
@@ -207,6 +211,13 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
updateResources();
}
+ protected void onMediaVisibilityChanged(Boolean visible) {
+ switchTileLayout();
+ if (mMediaVisibilityChangedListener != null) {
+ mMediaVisibilityChangedListener.accept(visible);
+ }
+ }
+
protected void addSecurityFooter() {
mSecurityFooter = new QSSecurityFooter(this, mContext);
}
@@ -479,6 +490,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
protected void onFinishInflate() {
super.onFinishInflate();
mFooter = findViewById(R.id.qs_footer);
+ mDivider = findViewById(R.id.divider);
switchTileLayout(true /* force */);
}
@@ -489,6 +501,13 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
private boolean switchTileLayout(boolean force) {
/** Whether or not the QuickQSPanel currently contains a media player. */
boolean horizontal = shouldUseHorizontalLayout();
+ if (mDivider != null) {
+ if (!horizontal && mUsingMediaPlayer && mMediaHost.getVisible()) {
+ mDivider.setVisibility(View.VISIBLE);
+ } else {
+ mDivider.setVisibility(View.GONE);
+ }
+ }
if (horizontal != mUsingHorizontalLayout || force) {
mUsingHorizontalLayout = horizontal;
View visibleView = horizontal ? mHorizontalLinearLayout : (View) mRegularTileLayout;
@@ -522,6 +541,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
updateTileLayoutMargins();
updateFooterMargin();
+ updateDividerMargin();
updateMediaHostContentMargins();
updateHorizontalLinearLayoutMargins();
updatePadding();
@@ -971,6 +991,11 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
return mSecurityFooter;
}
+ @Nullable
+ public View getDivider() {
+ return mDivider;
+ }
+
public void showDeviceMonitoringDialog() {
if (mSecurityFooter != null) {
mSecurityFooter.showDeviceMonitoringDialog();
@@ -986,6 +1011,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mContentMarginEnd - mVisualTilePadding);
updateMediaHostContentMargins();
updateFooterMargin();
+ updateDividerMargin();
}
private void updateFooterMargin() {
@@ -1027,6 +1053,11 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
updateMargins((View) mTileLayout, mVisualMarginStart, marginEnd);
}
+ private void updateDividerMargin() {
+ if (mDivider == null) return;
+ updateMargins(mDivider, mContentMarginStart, mContentMarginEnd);
+ }
+
/**
* Update the margins of the media hosts
*/
@@ -1065,6 +1096,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mHeaderContainer = headerContainer;
}
+ public void setMediaVisibilityChangedListener(Consumer<Boolean> visibilityChangedListener) {
+ mMediaVisibilityChangedListener = visibilityChangedListener;
+ }
+
private class H extends Handler {
private static final int SHOW_DETAIL = 1;
private static final int SET_TILE_VISIBILITY = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 87faaccf2063..795d0627c447 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -14,8 +14,8 @@
package com.android.systemui.qs.tileimpl;
-import static androidx.lifecycle.Lifecycle.State.DESTROYED;
import static androidx.lifecycle.Lifecycle.State.RESUMED;
+import static androidx.lifecycle.Lifecycle.State.STARTED;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_CLICK;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_LONG_PRESS;
@@ -432,17 +432,19 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
}
private void handleSetListeningInternal(Object listener, boolean listening) {
+ // This should be used to go from resumed to paused. Listening for ON_RESUME and ON_PAUSE
+ // in this lifecycle will determine the listening window.
if (listening) {
if (mListeners.add(listener) && mListeners.size() == 1) {
if (DEBUG) Log.d(TAG, "handleSetListening true");
- mLifecycle.markState(RESUMED);
+ mLifecycle.setCurrentState(RESUMED);
handleSetListening(listening);
refreshState(); // Ensure we get at least one refresh after listening.
}
} else {
if (mListeners.remove(listener) && mListeners.size() == 0) {
if (DEBUG) Log.d(TAG, "handleSetListening false");
- mLifecycle.markState(DESTROYED);
+ mLifecycle.setCurrentState(STARTED);
handleSetListening(listening);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
index d057a8a43c43..8347def2d430 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
@@ -97,6 +97,9 @@ public class ScreenRecordDialog extends Activity {
mModes);
a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mOptions.setAdapter(a);
+ mOptions.setOnItemClickListenerInt((parent, view, position, id) -> {
+ mAudioSwitch.setChecked(true);
+ });
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 33f0f4d8618b..9bbc4ddcc62c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -1105,14 +1105,19 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
return;
}
- Intent actionIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
+ PendingIntent actionIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
if (intent.getBooleanExtra(EXTRA_CANCEL_NOTIFICATION, false)) {
ScreenshotNotificationsController.cancelScreenshotNotification(context);
}
ActivityOptions opts = ActivityOptions.makeBasic();
opts.setDisallowEnterPictureInPictureWhileLaunching(
intent.getBooleanExtra(EXTRA_DISALLOW_ENTER_PIP, false));
- context.startActivityAsUser(actionIntent, opts.toBundle(), UserHandle.CURRENT);
+ try {
+ actionIntent.send(context, 0, null, null, null, null, opts.toBundle());
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Pending intent canceled", e);
+ }
+
};
if (mStatusBar != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index 10e6902f139e..468b9b16addb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -282,10 +282,14 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ // cancel current pending intent (if any) since clipData isn't used for matching
+ PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, 0,
+ sharingChooserIntent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+
// Create a share action for the notification
PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, sharingChooserIntent)
+ .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, pendingIntent)
.putExtra(GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP, true)
.putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
.putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
@@ -320,14 +324,17 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, 0,
+ editIntent, 0, null, UserHandle.CURRENT);
+
// Make sure pending intents for the system user are still unique across users
// by setting the (otherwise unused) request code to the current user id.
int requestCode = mContext.getUserId();
// Create a edit action
- PendingIntent editAction = PendingIntent.getBroadcast(context, requestCode,
+ PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, editIntent)
+ .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, pendingIntent)
.putExtra(GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION,
editIntent.getComponent() != null)
.putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
@@ -335,7 +342,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mSmartActionsEnabled)
.setAction(Intent.ACTION_EDIT)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
Icon.createWithResource(r, R.drawable.ic_screenshot_edit),
r.getString(com.android.internal.R.string.screenshot_edit), editAction);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 821144a7f12d..71e788375d5e 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -443,14 +443,10 @@ public class BrightnessController implements ToggleSlider.Listener {
max = mMaximumBacklight;
}
// convertGammaToLinearFloat returns 0-1
- if (BrightnessSynchronizer.brightnessFloatToInt(mContext, brightnessValue)
- == BrightnessSynchronizer.brightnessFloatToInt(mContext,
+ if (BrightnessSynchronizer.floatEquals(brightnessValue,
convertGammaToLinearFloat(mControl.getValue(), min, max))) {
- // If we have more resolution on the slider than we do in the actual setting, then
- // multiple slider positions will map to the same setting value. Thus, if we see a
- // setting value here that maps to the current slider position, we don't bother to
- // calculate the new slider position since it may differ and look like a brightness
- // change to the user even though it isn't one.
+ // If the value in the slider is equal to the value on the current brightness
+ // then the slider does not need to animate, since the brightness will not change.
return;
}
// Returns GAMMA_SPACE_MIN - GAMMA_SPACE_MAX
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 03a0d930a3d9..8a3819925f30 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -253,7 +253,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
mRotateSplitLayout = null;
}
- update(newConfig);
+ if (isSplitActive()) {
+ update(newConfig);
+ }
}
Handler getHandler() {
@@ -328,11 +330,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
mHandler.post(this::removeDivider);
}
- void onTasksReady() {
- mHandler.post(() -> update(mDisplayController.getDisplayContext(
- mContext.getDisplayId()).getResources().getConfiguration()));
- }
-
private void updateVisibility(final boolean visible) {
if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
if (mVisible != visible) {
@@ -387,6 +384,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
}
// Always set this because we could be entering split when mMinimized is already true
wct.setFocusable(mSplits.mPrimary.token, !mMinimized);
+ boolean onlyFocusable = true;
// Update home-stack resizability
final boolean homeResizableChanged = mHomeStackResizable != homeStackResizable;
@@ -395,6 +393,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
if (isDividerVisible()) {
WindowManagerProxy.applyHomeTasksMinimized(
mSplitLayout, mSplits.mSecondary.token, wct);
+ onlyFocusable = false;
}
}
@@ -416,7 +415,15 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
}
}
updateTouchable();
- mWindowManagerProxy.applySyncTransaction(wct);
+ if (onlyFocusable) {
+ // If we are only setting focusability, a sync transaction isn't necessary (in fact it
+ // can interrupt other animations), so see if it can be submitted on pending instead.
+ if (!mSplits.mDivider.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
+ WindowOrganizer.applyTransaction(wct);
+ }
+ } else {
+ mWindowManagerProxy.applySyncTransaction(wct);
+ }
}
void setAdjustedForIme(boolean adjustedForIme) {
@@ -524,7 +531,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
void ensureMinimizedSplit() {
setHomeMinimized(true /* minimized */, mHomeStackResizable);
- if (!isDividerVisible()) {
+ if (mView != null && !isDividerVisible()) {
// Wasn't in split-mode yet, so enter now.
if (DEBUG) {
Slog.d(TAG, " entering split mode with minimized=true");
@@ -535,7 +542,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
void ensureNormalSplit() {
setHomeMinimized(false /* minimized */, mHomeStackResizable);
- if (!isDividerVisible()) {
+ if (mView != null && !isDividerVisible()) {
// Wasn't in split-mode, so enter now.
if (DEBUG) {
Slog.d(TAG, " enter split mode unminimized ");
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
index d782a3cadc19..47c8c0ad8a4e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
@@ -29,6 +29,7 @@ import android.view.SurfaceControl;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import android.window.WindowOrganizer;
import androidx.annotation.Nullable;
@@ -173,46 +174,50 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
}
private void updateImeAdjustState() {
- // Reposition the server's secondary split position so that it evaluates
- // insets properly.
- WindowContainerTransaction wct = new WindowContainerTransaction();
- final SplitDisplayLayout splitLayout = getLayout();
- if (mTargetAdjusted) {
- splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
- wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary);
- // "Freeze" the configuration size so that the app doesn't get a config
- // or relaunch. This is required because normally nav-bar contributes
- // to configuration bounds (via nondecorframe).
- Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
- .windowConfiguration.getAppBounds());
- adjustAppBounds.offset(0, splitLayout.mAdjustedSecondary.top
- - splitLayout.mSecondary.top);
- wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
- wct.setScreenSizeDp(mSplits.mSecondary.token,
- mSplits.mSecondary.configuration.screenWidthDp,
- mSplits.mSecondary.configuration.screenHeightDp);
-
- wct.setBounds(mSplits.mPrimary.token, splitLayout.mAdjustedPrimary);
- adjustAppBounds = new Rect(mSplits.mPrimary.configuration
- .windowConfiguration.getAppBounds());
- adjustAppBounds.offset(0, splitLayout.mAdjustedPrimary.top
- - splitLayout.mPrimary.top);
- wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
- wct.setScreenSizeDp(mSplits.mPrimary.token,
- mSplits.mPrimary.configuration.screenWidthDp,
- mSplits.mPrimary.configuration.screenHeightDp);
- } else {
- wct.setBounds(mSplits.mSecondary.token, splitLayout.mSecondary);
- wct.setAppBounds(mSplits.mSecondary.token, null);
- wct.setScreenSizeDp(mSplits.mSecondary.token,
- SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
- wct.setBounds(mSplits.mPrimary.token, splitLayout.mPrimary);
- wct.setAppBounds(mSplits.mPrimary.token, null);
- wct.setScreenSizeDp(mSplits.mPrimary.token,
- SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
- }
+ if (mAdjusted != mTargetAdjusted) {
+ // Reposition the server's secondary split position so that it evaluates
+ // insets properly.
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ final SplitDisplayLayout splitLayout = getLayout();
+ if (mTargetAdjusted) {
+ splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
+ wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary);
+ // "Freeze" the configuration size so that the app doesn't get a config
+ // or relaunch. This is required because normally nav-bar contributes
+ // to configuration bounds (via nondecorframe).
+ Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
+ .windowConfiguration.getAppBounds());
+ adjustAppBounds.offset(0, splitLayout.mAdjustedSecondary.top
+ - splitLayout.mSecondary.top);
+ wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
+ wct.setScreenSizeDp(mSplits.mSecondary.token,
+ mSplits.mSecondary.configuration.screenWidthDp,
+ mSplits.mSecondary.configuration.screenHeightDp);
+
+ wct.setBounds(mSplits.mPrimary.token, splitLayout.mAdjustedPrimary);
+ adjustAppBounds = new Rect(mSplits.mPrimary.configuration
+ .windowConfiguration.getAppBounds());
+ adjustAppBounds.offset(0, splitLayout.mAdjustedPrimary.top
+ - splitLayout.mPrimary.top);
+ wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
+ wct.setScreenSizeDp(mSplits.mPrimary.token,
+ mSplits.mPrimary.configuration.screenWidthDp,
+ mSplits.mPrimary.configuration.screenHeightDp);
+ } else {
+ wct.setBounds(mSplits.mSecondary.token, splitLayout.mSecondary);
+ wct.setAppBounds(mSplits.mSecondary.token, null);
+ wct.setScreenSizeDp(mSplits.mSecondary.token,
+ SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
+ wct.setBounds(mSplits.mPrimary.token, splitLayout.mPrimary);
+ wct.setAppBounds(mSplits.mPrimary.token, null);
+ wct.setScreenSizeDp(mSplits.mPrimary.token,
+ SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
+ }
- mSplits.mDivider.getWmProxy().applySyncTransaction(wct);
+ if (!mSplits.mDivider.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
+ WindowOrganizer.applyTransaction(wct);
+ }
+ }
// Update all the adjusted-for-ime states
if (!mPaused) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 42d8c959371f..6f554e698c58 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -352,8 +352,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
minimizeLeft + mMinimizedShadow.getMeasuredWidth(),
minimizeTop + mMinimizedShadow.getMeasuredHeight());
if (changed) {
- mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
- mHandle.getRight(), mHandle.getBottom()));
notifySplitScreenBoundsChanged();
}
}
@@ -679,6 +677,14 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private void notifySplitScreenBoundsChanged() {
mOtherTaskRect.set(mSplitLayout.mSecondary);
+ mTmpRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(), mHandle.getBottom());
+ if (isHorizontalDivision()) {
+ mTmpRect.offsetTo(0, mDividerPositionY);
+ } else {
+ mTmpRect.offsetTo(mDividerPositionX, 0);
+ }
+ mWindowManagerProxy.setTouchRegion(mTmpRect);
+
mTmpRect.set(mSplitLayout.mDisplayLayout.stableInsets());
switch (mSplitLayout.getPrimarySplitSide()) {
case WindowManager.DOCKED_LEFT:
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index 6751e8d6223d..4a2cad705c17 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -113,8 +113,6 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
t.apply();
releaseTransaction(t);
-
- mDivider.onTasksReady();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 8c7e071e0d3e..a1444532bd5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -25,6 +25,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.UserInfo;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.hardware.biometrics.BiometricSourceType;
@@ -34,12 +35,16 @@ import android.os.BatteryManager;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.widget.ViewClippingUtil;
@@ -96,6 +101,7 @@ public class KeyguardIndicationController implements StateListener,
private final SettableWakeLock mWakeLock;
private final DockManager mDockManager;
private final DevicePolicyManager mDevicePolicyManager;
+ private final UserManager mUserManager;
private BroadcastReceiver mBroadcastReceiver;
private LockscreenLockIconController mLockIconController;
@@ -142,7 +148,8 @@ public class KeyguardIndicationController implements StateListener,
DockManager dockManager,
BroadcastDispatcher broadcastDispatcher,
DevicePolicyManager devicePolicyManager,
- IBatteryStats iBatteryStats) {
+ IBatteryStats iBatteryStats,
+ UserManager userManager) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
mDevicePolicyManager = devicePolicyManager;
@@ -155,6 +162,7 @@ public class KeyguardIndicationController implements StateListener,
mWakeLock = new SettableWakeLock(
wakeLockBuilder.setTag("Doze:KeyguardIndication").build(), TAG);
mBatteryInfo = iBatteryStats;
+ mUserManager = userManager;
mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
@@ -180,8 +188,10 @@ public class KeyguardIndicationController implements StateListener,
updateDisclosure();
}
};
- mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, new IntentFilter(
- DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, intentFilter);
}
}
@@ -223,9 +233,8 @@ public class KeyguardIndicationController implements StateListener,
private void updateDisclosure() {
// NOTE: Because this uses IPC, avoid calling updateDisclosure() on a critical path.
- if (whitelistIpcs(mDevicePolicyManager::isDeviceManaged)) {
- final CharSequence organizationName =
- mDevicePolicyManager.getDeviceOwnerOrganizationName();
+ if (whitelistIpcs(this::isOrganizationOwnedDevice)) {
+ CharSequence organizationName = getOrganizationOwnedDeviceOrganizationName();
if (organizationName != null) {
mDisclosure.switchIndication(mContext.getResources().getString(
R.string.do_disclosure_with_name, organizationName));
@@ -238,6 +247,38 @@ public class KeyguardIndicationController implements StateListener,
}
}
+ private boolean isOrganizationOwnedDevice() {
+ return mDevicePolicyManager.isDeviceManaged()
+ || mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile();
+ }
+
+ @Nullable
+ private CharSequence getOrganizationOwnedDeviceOrganizationName() {
+ if (mDevicePolicyManager.isDeviceManaged()) {
+ return mDevicePolicyManager.getDeviceOwnerOrganizationName();
+ } else if (mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()) {
+ return getWorkProfileOrganizationName();
+ }
+ return null;
+ }
+
+ private CharSequence getWorkProfileOrganizationName() {
+ final int profileId = getWorkProfileUserId(UserHandle.myUserId());
+ if (profileId == UserHandle.USER_NULL) {
+ return null;
+ }
+ return mDevicePolicyManager.getOrganizationNameForUser(profileId);
+ }
+
+ private int getWorkProfileUserId(int userId) {
+ for (final UserInfo userInfo : mUserManager.getProfiles(userId)) {
+ if (userInfo.isManagedProfile()) {
+ return userInfo.id;
+ }
+ }
+ return UserHandle.USER_NULL;
+ }
+
public void setVisible(boolean visible) {
mVisible = visible;
mIndicationArea.setVisibility(visible ? View.VISIBLE : View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 33771449abc9..423f85f2ddd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -178,6 +178,7 @@ public final class NotificationEntry extends ListEntry {
private int mBucket = BUCKET_ALERTING;
@Nullable private Long mPendingAnimationDuration;
private boolean mIsMarkedForUserTriggeredMovement;
+ private boolean mShelfIconVisible;
/**
* @param sbn the StatusBarNotification from system server
@@ -431,6 +432,7 @@ public final class NotificationEntry extends ListEntry {
//TODO: This will go away when we have a way to bind an entry to a row
public void setRow(ExpandableNotificationRow row) {
this.row = row;
+ updateShelfIconVisibility();
}
public ExpandableNotificationRowController getRowController() {
@@ -951,6 +953,18 @@ public final class NotificationEntry extends ListEntry {
return mIsMarkedForUserTriggeredMovement;
}
+ /** Whether or not the icon for this notification is visible in the shelf. */
+ public void setShelfIconVisible(boolean shelfIconVisible) {
+ mShelfIconVisible = shelfIconVisible;
+ updateShelfIconVisibility();
+ }
+
+ private void updateShelfIconVisibility() {
+ if (row != null) {
+ row.setShelfIconVisible(mShelfIconVisible);
+ }
+ }
+
/**
* Mark this entry for movement triggered by a user action (ex: changing the priorirty of a
* conversation). This can then be used for custom animations.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 5c802bd2e5b7..df1de63b65a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -24,6 +24,7 @@ import android.os.Handler;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.dagger.qualifiers.Background;
@@ -116,7 +117,8 @@ public interface NotificationsModule {
ChannelEditorDialogController channelEditorDialogController,
CurrentUserContextTracker contextTracker,
Provider<PriorityOnboardingDialogController.Builder> builderProvider,
- BubbleController bubbleController) {
+ BubbleController bubbleController,
+ UiEventLogger uiEventLogger) {
return new NotificationGutsManager(
context,
visualStabilityManager,
@@ -131,7 +133,8 @@ public interface NotificationsModule {
channelEditorDialogController,
contextTracker,
builderProvider,
- bubbleController);
+ bubbleController,
+ uiEventLogger);
}
/** Provides an instance of {@link VisualStabilityManager} */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
index 011ad19b41db..13f7a53f5e54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
@@ -96,13 +96,11 @@ class IconManager @Inject constructor(
val shelfIcon = iconBuilder.createIconView(entry)
shelfIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE
- shelfIcon.visibility = View.INVISIBLE
// TODO: This doesn't belong here
shelfIcon.setOnVisibilityChangedListener { newVisibility: Int ->
- if (entry.row != null) {
- entry.row.setShelfIconVisible(newVisibility == View.VISIBLE)
- }
+ entry.setShelfIconVisible(newVisibility == View.VISIBLE)
}
+ shelfIcon.visibility = View.INVISIBLE
// Construct the aod icon view.
val aodIcon = iconBuilder.createIconView(entry)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
index 9a25c480dfe8..c147023edf8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
@@ -16,6 +16,13 @@
package com.android.systemui.statusbar.notification.logging;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_FOREGROUND_SERVICE;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_HEADS_UP;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
+
import android.annotation.Nullable;
import android.service.notification.StatusBarNotification;
@@ -23,6 +30,7 @@ import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.nano.Notifications;
+import com.android.systemui.statusbar.notification.stack.PriorityBucket;
import java.util.List;
/**
@@ -84,7 +92,7 @@ public interface NotificationPanelLogger {
if (n.getNotification() != null) {
proto.isGroupSummary = n.getNotification().isGroupSummary();
}
- proto.section = 1 + ne.getBucket(); // We want 0 to mean not set / unknown
+ proto.section = toNotificationSection(ne.getBucket());
proto_array[i] = proto;
}
++i;
@@ -92,4 +100,25 @@ public interface NotificationPanelLogger {
notificationList.notifications = proto_array;
return notificationList;
}
+
+ /**
+ * Maps PriorityBucket enum to Notification.SECTION constant. The two lists should generally
+ * use matching names, but the values may differ, because PriorityBucket order changes from
+ * time to time, while logs need to have stable meanings.
+ * @param bucket PriorityBucket constant
+ * @return Notification.SECTION constant
+ */
+ static int toNotificationSection(@PriorityBucket int bucket) {
+ switch(bucket) {
+ case BUCKET_MEDIA_CONTROLS : return Notifications.Notification.SECTION_MEDIA_CONTROLS;
+ case BUCKET_HEADS_UP: return Notifications.Notification.SECTION_HEADS_UP;
+ case BUCKET_FOREGROUND_SERVICE:
+ return Notifications.Notification.SECTION_FOREGROUND_SERVICE;
+ case BUCKET_PEOPLE: return Notifications.Notification.SECTION_PEOPLE;
+ case BUCKET_ALERTING: return Notifications.Notification.SECTION_ALERTING;
+ case BUCKET_SILENT: return Notifications.Notification.SECTION_SILENT;
+ }
+ return Notifications.Notification.SECTION_UNKNOWN;
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
index 552a5fb40a1c..c2ab2758dd74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
@@ -33,13 +33,16 @@ message Notification {
optional bool is_group_summary = 5;
// The section of the shade that the notification is in.
- // See NotificationSectionsManager.PriorityBucket.
+ // Sections follow NotificationSectionsManager.PriorityBucket but enum constants do not,
+ // as PriorityBucket order changes from time to time, while logs need to have stable meanings.
enum NotificationSection {
SECTION_UNKNOWN = 0;
SECTION_HEADS_UP = 1;
- SECTION_PEOPLE = 2;
- SECTION_ALERTING = 3;
- SECTION_SILENT = 4;
+ SECTION_MEDIA_CONTROLS = 2;
+ SECTION_PEOPLE = 3;
+ SECTION_ALERTING = 4;
+ SECTION_SILENT = 5;
+ SECTION_FOREGROUND_SERVICE = 6;
}
optional NotificationSection section = 6;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
index e445c9d73bbb..28c53dc6d9b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
@@ -31,6 +31,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -50,6 +51,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
private MetricsLogger mMetricsLogger;
private OnSettingsClickListener mOnSettingsClickListener;
private NotificationGuts mGutsContainer;
+ private UiEventLogger mUiEventLogger;
private OnClickListener mOnOk = v -> {
mGutsContainer.closeControls(v, false);
@@ -66,6 +68,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
public void bindGuts(final PackageManager pm,
final OnSettingsClickListener onSettingsClick,
final StatusBarNotification sbn,
+ final UiEventLogger uiEventLogger,
ArraySet<Integer> activeOps) {
mPkg = sbn.getPackageName();
mSbn = sbn;
@@ -73,11 +76,13 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
mAppName = mPkg;
mOnSettingsClickListener = onSettingsClick;
mAppOps = activeOps;
+ mUiEventLogger = uiEventLogger;
bindHeader();
bindPrompt();
bindButtons();
+ logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN);
mMetricsLogger = new MetricsLogger();
mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true);
}
@@ -188,6 +193,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
@Override
public boolean handleCloseControls(boolean save, boolean force) {
+ logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_CLOSE);
if (mMetricsLogger != null) {
mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
}
@@ -198,4 +204,11 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
public int getActualHeight() {
return getHeight();
}
+
+ private void logUiEvent(NotificationAppOpsEvent event) {
+ if (mSbn != null) {
+ mUiEventLogger.logWithInstanceId(event,
+ mSbn.getUid(), mSbn.getPackageName(), mSbn.getInstanceId());
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 7ed8350249ec..ccfd8a329ffd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -769,10 +769,6 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
return mContentTranslation;
}
- public boolean wantsAddAndRemoveAnimations() {
- return true;
- }
-
/** Sets whether this view is the first notification in a section. */
public void setFirstInSection(boolean firstInSection) {
mFirstInSection = firstInSection;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationAppOpsEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationAppOpsEvent.java
new file mode 100644
index 000000000000..c856245ebe83
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationAppOpsEvent.java
@@ -0,0 +1,41 @@
+/*
+ * 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.row;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+
+enum NotificationAppOpsEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "User opened app ops controls on a notification (for active "
+ + "privacy-sensitive permissions usage)")
+ NOTIFICATION_APP_OPS_OPEN(597),
+
+ @UiEvent(doc = "User closed app ops controls")
+ NOTIFICATION_APP_OPS_CLOSE(598),
+
+ @UiEvent(doc = "User clicked through to settings in app ops controls")
+ NOTIFICATION_APP_OPS_SETTINGS_CLICK(599);
+
+ private final int mId;
+ NotificationAppOpsEvent(int id) {
+ mId = id;
+ }
+ @Override public int getId() {
+ return mId;
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationControlsEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationControlsEvent.java
new file mode 100644
index 000000000000..6833326d47e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationControlsEvent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+
+enum NotificationControlsEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "The user opened the notification inline controls.")
+ NOTIFICATION_CONTROLS_OPEN(594),
+
+ @UiEvent(doc = "In notification inline controls, the user saved a notification channel "
+ + "importance change.")
+ NOTIFICATION_CONTROLS_SAVE_IMPORTANCE(595),
+
+ @UiEvent(doc = "The user closed the notification inline controls.")
+ NOTIFICATION_CONTROLS_CLOSE(596);
+
+ private final int mId;
+ NotificationControlsEvent(int id) {
+ mId = id;
+ }
+ @Override public int getId() {
+ return mId;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 8337cbe449d5..24883f51a984 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -41,6 +41,7 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.notification.ConversationIconFactory;
import com.android.systemui.Dependency;
@@ -121,6 +122,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
private final ShortcutManager mShortcutManager;
private final CurrentUserContextTracker mContextTracker;
private final Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider;
+ private final UiEventLogger mUiEventLogger;
/**
* Injected constructor. See {@link NotificationsModule}.
@@ -135,7 +137,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
ChannelEditorDialogController channelEditorDialogController,
CurrentUserContextTracker contextTracker,
Provider<PriorityOnboardingDialogController.Builder> builderProvider,
- BubbleController bubbleController) {
+ BubbleController bubbleController,
+ UiEventLogger uiEventLogger) {
mContext = context;
mVisualStabilityManager = visualStabilityManager;
mStatusBarLazy = statusBarLazy;
@@ -150,6 +153,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mBuilderProvider = builderProvider;
mChannelEditorDialogController = channelEditorDialogController;
mBubbleController = bubbleController;
+ mUiEventLogger = uiEventLogger;
}
public void setUpWithPresenter(NotificationPresenter presenter,
@@ -315,12 +319,16 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
AppOpsInfo.OnSettingsClickListener onSettingsClick =
(View v, String pkg, int uid, ArraySet<Integer> ops) -> {
- mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
- guts.resetFalsingCheck();
- startAppOpsSettingsActivity(pkg, uid, ops, row);
+ mUiEventLogger.logWithInstanceId(
+ NotificationAppOpsEvent.NOTIFICATION_APP_OPS_SETTINGS_CLICK,
+ sbn.getUid(), sbn.getPackageName(), sbn.getInstanceId());
+ mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
+ guts.resetFalsingCheck();
+ startAppOpsSettingsActivity(pkg, uid, ops, row);
};
if (!row.getEntry().mActiveAppOps.isEmpty()) {
- appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, row.getEntry().mActiveAppOps);
+ appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, mUiEventLogger,
+ row.getEntry().mActiveAppOps);
}
}
@@ -370,6 +378,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
row.getEntry(),
onSettingsClick,
onAppSettingsClick,
+ mUiEventLogger,
mDeviceProvisionedController.isDeviceProvisioned(),
row.getIsNonblockable(),
mHighPriorityProvider.isHighPriority(row.getEntry()));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index a131ebef77db..f0c93b10578c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -56,6 +56,7 @@ import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -122,6 +123,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
private OnAppSettingsClickListener mAppSettingsClickListener;
private NotificationGuts mGutsContainer;
private Drawable mPkgIcon;
+ private UiEventLogger mUiEventLogger;
@VisibleForTesting
boolean mSkipPost = false;
@@ -182,6 +184,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
NotificationEntry entry,
OnSettingsClickListener onSettingsClick,
OnAppSettingsClickListener onAppSettingsClick,
+ UiEventLogger uiEventLogger,
boolean isDeviceProvisioned,
boolean isNonblockable,
boolean wasShownHighPriority)
@@ -205,6 +208,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
mAppUid = mSbn.getUid();
mDelegatePkg = mSbn.getOpPkg();
mIsDeviceProvisioned = isDeviceProvisioned;
+ mUiEventLogger = uiEventLogger;
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
@@ -223,6 +227,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
bindInlineControls();
+ logUiEvent(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN);
mMetricsLogger.write(notificationControlsLogMaker());
}
@@ -397,6 +402,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
*/
private void updateImportance() {
if (mChosenImportance != null) {
+ logUiEvent(NotificationControlsEvent.NOTIFICATION_CONTROLS_SAVE_IMPORTANCE);
mMetricsLogger.write(importanceChangeLogMaker());
int newImportance = mChosenImportance;
@@ -483,6 +489,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
bindInlineControls();
+ logUiEvent(NotificationControlsEvent.NOTIFICATION_CONTROLS_CLOSE);
mMetricsLogger.write(notificationControlsLogMaker().setType(MetricsEvent.TYPE_CLOSE));
}
@@ -627,6 +634,13 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
}
}
+ private void logUiEvent(NotificationControlsEvent event) {
+ if (mSbn != null) {
+ mUiEventLogger.logWithInstanceId(event,
+ mSbn.getUid(), mSbn.getPackageName(), mSbn.getInstanceId());
+ }
+ }
+
/**
* Returns a LogMaker with all available notification information.
* Caller should set category, type, and maybe subtype, before passing it to mMetricsLogger.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index b4220f1da715..11e698b03823 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -83,6 +83,8 @@ public class AmbientState {
private float mDozeAmount = 0.0f;
private HeadsUpManager mHeadUpManager;
private Runnable mOnPulseHeightChangedListener;
+ private ExpandableNotificationRow mTrackedHeadsUpRow;
+ private float mAppearFraction;
public AmbientState(
Context context,
@@ -543,4 +545,27 @@ public class AmbientState {
public Runnable getOnPulseHeightChangedListener() {
return mOnPulseHeightChangedListener;
}
+
+ public void setTrackedHeadsUpRow(ExpandableNotificationRow row) {
+ mTrackedHeadsUpRow = row;
+ }
+
+ /**
+ * Returns the currently tracked heads up row, if there is one and it is currently above the
+ * shelf (still appearing).
+ */
+ public ExpandableNotificationRow getTrackedHeadsUpRow() {
+ if (mTrackedHeadsUpRow == null || !mTrackedHeadsUpRow.isAboveShelf()) {
+ return null;
+ }
+ return mTrackedHeadsUpRow;
+ }
+
+ public void setAppearFraction(float appearFraction) {
+ mAppearFraction = appearFraction;
+ }
+
+ public float getAppearFraction() {
+ return mAppearFraction;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
index 383f2a2b0e9f..040f707e12f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
@@ -50,9 +50,4 @@ public class MediaHeaderView extends ExpandableView {
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
}
-
- @Override
- public boolean wantsAddAndRemoveAnimations() {
- return false;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 684bf1958154..b9d31a93f408 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -97,6 +97,7 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
@@ -200,6 +201,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private final KeyguardBypassController mKeyguardBypassController;
private final DynamicPrivacyController mDynamicPrivacyController;
private final SysuiStatusBarStateController mStatusbarStateController;
+ private final KeyguardMediaController mKeyguardMediaController;
private ExpandHelper mExpandHelper;
private final NotificationSwipeHelper mSwipeHelper;
@@ -533,6 +535,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private float mLastSentAppear;
private float mLastSentExpandedHeight;
private boolean mWillExpand;
+ private int mGapHeight;
private int mWaterfallTopInset;
@@ -552,6 +555,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
SysuiStatusBarStateController statusBarStateController,
HeadsUpManagerPhone headsUpManager,
KeyguardBypassController keyguardBypassController,
+ KeyguardMediaController keyguardMediaController,
FalsingManager falsingManager,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGutsManager notificationGutsManager,
@@ -670,6 +674,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
initializeForegroundServiceSection(fgsFeatureController);
mUiEventLogger = uiEventLogger;
mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
+ mKeyguardMediaController = keyguardMediaController;
+ keyguardMediaController.setVisibilityChangedListener((visible) -> {
+ if (visible) {
+ generateAddAnimation(keyguardMediaController.getView(), false /*fromMoreCard */);
+ } else {
+ generateRemoveAnimation(keyguardMediaController.getView());
+ }
+ requestChildrenUpdate();
+ return null;
+ });
}
private void initializeForegroundServiceSection(
@@ -1047,6 +1061,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
Resources res = context.getResources();
mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
+ mGapHeight = res.getDimensionPixelSize(R.dimen.notification_section_divider_height);
mStackScrollAlgorithm.initView(context);
mAmbientState.reload(context);
mPaddingBetweenElements = Math.max(1,
@@ -1407,14 +1422,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
// start
translationY = height - appearStartPosition + getExpandTranslationStart();
}
+ stackHeight = (int) (height - translationY);
if (isHeadsUpTransition()) {
- stackHeight =
- getFirstVisibleSection().getFirstVisibleChild().getPinnedHeadsUpHeight();
translationY = MathUtils.lerp(mHeadsUpInset - mTopPadding, 0, appearFraction);
- } else {
- stackHeight = (int) (height - translationY);
}
}
+ mAmbientState.setAppearFraction(appearFraction);
if (stackHeight != mCurrentStackHeight) {
mCurrentStackHeight = stackHeight;
updateAlgorithmHeightAndPadding();
@@ -1532,17 +1545,18 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private float getAppearEndPosition() {
- int appearPosition;
- int notGoneChildCount = getNotGoneChildCount();
- if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
+ int appearPosition = 0;
+ int visibleNotifCount = getVisibleNotificationCount();
+ if (mEmptyShadeView.getVisibility() == GONE && visibleNotifCount > 0) {
if (isHeadsUpTransition()
|| (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDozing())) {
- appearPosition = getTopHeadsUpPinnedHeight();
- } else {
- appearPosition = 0;
- if (notGoneChildCount >= 1 && mShelf.getVisibility() != GONE) {
- appearPosition += mShelf.getIntrinsicHeight();
+ if (mShelf.getVisibility() != GONE && visibleNotifCount > 1) {
+ appearPosition += mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
}
+ appearPosition += getTopHeadsUpPinnedHeight()
+ + getPositionInLinearLayout(mAmbientState.getTrackedHeadsUpRow());
+ } else if (mShelf.getVisibility() != GONE) {
+ appearPosition += mShelf.getIntrinsicHeight();
}
} else {
appearPosition = mEmptyShadeView.getHeight();
@@ -1552,9 +1566,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private boolean isHeadsUpTransition() {
- NotificationSection firstVisibleSection = getFirstVisibleSection();
- return mTrackingHeadsUp && firstVisibleSection != null
- && firstVisibleSection.getFirstVisibleChild().isAboveShelf();
+ return mAmbientState.getTrackedHeadsUpRow() != null;
}
/**
@@ -2962,7 +2974,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
public int getLayoutMinHeight() {
if (isHeadsUpTransition()) {
- return getTopHeadsUpPinnedHeight();
+ ExpandableNotificationRow trackedHeadsUpRow = mAmbientState.getTrackedHeadsUpRow();
+ if (trackedHeadsUpRow.isAboveShelf()) {
+ int hunDistance = (int) MathUtils.lerp(
+ 0,
+ getPositionInLinearLayout(trackedHeadsUpRow),
+ mAmbientState.getAppearFraction());
+ return getTopHeadsUpPinnedHeight() + hunDistance;
+ } else {
+ return getTopHeadsUpPinnedHeight();
+ }
}
return mShelf.getVisibility() == GONE ? 0 : mShelf.getIntrinsicHeight();
}
@@ -3101,9 +3122,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*/
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private boolean generateRemoveAnimation(ExpandableView child) {
- if (!child.wantsAddAndRemoveAnimations()) {
- return false;
- }
if (removeRemovedChildFromHeadsUpChangeAnimations(child)) {
mAddedHeadsUpChildren.remove(child);
return false;
@@ -3458,8 +3476,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {
- if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress && !isFullyHidden()
- && child.wantsAddAndRemoveAnimations()) {
+ if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress && !isFullyHidden()) {
// Generate Animations
mChildrenToAddAnimated.add(child);
if (fromMoreCard) {
@@ -3654,6 +3671,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
ignoreChildren = false;
}
childWasSwipedOut |= Math.abs(row.getTranslation()) == row.getWidth();
+ } else if (child instanceof MediaHeaderView) {
+ childWasSwipedOut = true;
}
if (!childWasSwipedOut) {
Rect clipBounds = child.getClipBounds();
@@ -5082,8 +5101,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public int getFooterViewHeight() {
- return mFooterView == null ? 0 : mFooterView.getHeight() + mPaddingBetweenElements;
+ public int getFooterViewHeightWithPadding() {
+ return mFooterView == null ? 0 : mFooterView.getHeight()
+ + mPaddingBetweenElements
+ + mGapHeight;
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5284,6 +5305,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setTrackingHeadsUp(ExpandableNotificationRow row) {
+ mAmbientState.setTrackedHeadsUpRow(row);
mTrackingHeadsUp = row != null;
mRoundnessManager.setTrackingHeadsUp(row);
}
@@ -6370,7 +6392,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public void onDragCancelled(View v) {
setSwipingInProgress(false);
- mFalsingManager.onNotificatonStopDismissing();
+ mFalsingManager.onNotificationStopDismissing();
}
/**
@@ -6470,7 +6492,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public void onBeginDrag(View v) {
- mFalsingManager.onNotificatonStartDismissing();
+ mFalsingManager.onNotificationStartDismissing();
setSwipingInProgress(true);
mAmbientState.onBeginDrag((ExpandableView) v);
updateContinuousShadowDrawing();
@@ -6629,7 +6651,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
/* Only ever called as a consequence of a lockscreen expansion gesture. */
@Override
public boolean onDraggedDown(View startingChild, int dragLengthY) {
- if (mStatusBarState == StatusBarState.KEYGUARD && hasActiveNotifications()) {
+ boolean canDragDown = hasActiveNotifications()
+ || mKeyguardMediaController.getView().getVisibility() == VISIBLE;
+ if (mStatusBarState == StatusBarState.KEYGUARD && canDragDown) {
mLockscreenGestureLogger.write(
MetricsEvent.ACTION_LS_SHADE,
(int) (dragLengthY / mDisplayMetrics.density),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index a4598e9cec9f..541c7845a5d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
+import android.util.MathUtils;
import android.view.View;
import android.view.ViewGroup;
@@ -441,7 +442,7 @@ public class StackScrollAlgorithm {
} else if (isEmptyShadeView) {
childViewState.yTranslation = ambientState.getInnerHeight() - childHeight
+ ambientState.getStackTranslation() * 0.25f;
- } else {
+ } else if (child != ambientState.getTrackedHeadsUpRow()) {
clampPositionToShelf(child, childViewState, ambientState);
}
@@ -539,6 +540,19 @@ public class StackScrollAlgorithm {
private void updateHeadsUpStates(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
+
+ // Move the tracked heads up into position during the appear animation, by interpolating
+ // between the HUN inset (where it will appear as a HUN) and the end position in the shade
+ ExpandableNotificationRow trackedHeadsUpRow = ambientState.getTrackedHeadsUpRow();
+ if (trackedHeadsUpRow != null) {
+ ExpandableViewState childState = trackedHeadsUpRow.getViewState();
+ if (childState != null) {
+ float endPosition = childState.yTranslation - ambientState.getStackTranslation();
+ childState.yTranslation = MathUtils.lerp(
+ mHeadsUpInset, endPosition, ambientState.getAppearFraction());
+ }
+ }
+
ExpandableNotificationRow topHeadsUpEntry = null;
for (int i = 0; i < childCount; i++) {
View child = algorithmState.visibleChildren.get(i);
@@ -561,7 +575,7 @@ public class StackScrollAlgorithm {
&& !row.showingPulsing()) {
// Ensure that the heads up is always visible even when scrolled off
clampHunToTop(ambientState, row, childState);
- if (i == 0 && row.isAboveShelf()) {
+ if (isTopEntry && row.isAboveShelf()) {
// the first hun can't get off screen.
clampHunToMaxTranslation(ambientState, row, childState);
childState.hidden = false;
@@ -636,9 +650,13 @@ public class StackScrollAlgorithm {
return;
}
+ ExpandableNotificationRow trackedHeadsUpRow = ambientState.getTrackedHeadsUpRow();
+ boolean isBeforeTrackedHeadsUp = trackedHeadsUpRow != null
+ && mHostView.indexOfChild(child) < mHostView.indexOfChild(trackedHeadsUpRow);
+
int shelfStart = ambientState.getInnerHeight()
- ambientState.getShelf().getIntrinsicHeight();
- if (ambientState.isAppearing() && !child.isAboveShelf()) {
+ if (ambientState.isAppearing() && !child.isAboveShelf() && !isBeforeTrackedHeadsUp) {
// Don't show none heads-up notifications while in appearing phase.
childViewState.yTranslation = Math.max(childViewState.yTranslation, shelfStart);
}
@@ -695,7 +713,8 @@ public class StackScrollAlgorithm {
}
childViewState.zTranslation = baseZ
+ childrenOnTop * zDistanceBetweenElements;
- } else if (i == 0 && (child.isAboveShelf() || child.showingPulsing())) {
+ } else if (child == ambientState.getTrackedHeadsUpRow()
+ || (i == 0 && (child.isAboveShelf() || child.showingPulsing()))) {
// In case this is a new view that has never been measured before, we don't want to
// elevate if we are currently expanded more then the notification
int shelfHeight = ambientState.getShelf() == null ? 0 :
@@ -703,7 +722,7 @@ public class StackScrollAlgorithm {
float shelfStart = ambientState.getInnerHeight()
- shelfHeight + ambientState.getTopPadding()
+ ambientState.getStackTranslation();
- float notificationEnd = childViewState.yTranslation + child.getPinnedHeadsUpHeight()
+ float notificationEnd = childViewState.yTranslation + child.getIntrinsicHeight()
+ mPaddingBetweenElements;
if (shelfStart > notificationEnd) {
childViewState.zTranslation = baseZ;
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 cad1c91975bf..304fe0090e77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -23,7 +23,6 @@ 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;
import android.graphics.Point;
import android.graphics.PointF;
@@ -31,15 +30,11 @@ import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.DeviceConfig;
-import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
@@ -92,8 +87,6 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
private static final String TAG = "EdgeBackGestureHandler";
private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
"gestures.back_timeout", 250);
- private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform";
-
private ISystemGestureExclusionListener mGestureExclusionListener =
new ISystemGestureExclusionListener.Stub() {
@@ -119,14 +112,6 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
}
};
- private final ContentObserver mFixedRotationObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- updatedFixedRotation();
- }
- };
-
private TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {
@@ -136,6 +121,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
private final Context mContext;
private final OverviewProxyService mOverviewProxyService;
+ private final Runnable mStateChangeCallback;
+
private final PluginManager mPluginManager;
// Activities which should not trigger Back gesture.
private final List<ComponentName> mGestureBlockingActivities = new ArrayList<>();
@@ -162,7 +149,6 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
// We temporarily disable back gesture when user is quickswitching
// between apps of different orientations
private boolean mDisabledForQuickstep;
- private boolean mFixedRotationFlagEnabled;
private final PointF mDownPoint = new PointF();
private final PointF mEndPoint = new PointF();
@@ -212,13 +198,15 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
};
public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
- SysUiState sysUiFlagContainer, PluginManager pluginManager) {
+ SysUiState sysUiFlagContainer, PluginManager pluginManager,
+ Runnable stateChangeCallback) {
super(Dependency.get(BroadcastDispatcher.class));
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = context.getMainExecutor();
mOverviewProxyService = overviewProxyService;
mPluginManager = pluginManager;
+ mStateChangeCallback = stateChangeCallback;
ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(com.android.internal.R.string.config_recentsComponentName));
if (recentsComponentName != null) {
@@ -242,13 +230,13 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
Log.e(TAG, "Failed to add gesture blocking activities", e);
}
}
- Dependency.get(ProtoTracer.class).add(this);
+ Dependency.get(ProtoTracer.class).add(this);
mLongPressTimeout = Math.min(MAX_LONG_PRESS_TIMEOUT,
ViewConfiguration.getLongPressTimeout());
mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(
- mContext.getMainThreadHandler(), mContext, this::updateCurrentUserResources);
+ mContext.getMainThreadHandler(), mContext, this::onNavigationSettingsChanged);
updateCurrentUserResources();
sysUiFlagContainer.addCallback(sysUiFlags -> mSysUiFlags = sysUiFlags);
@@ -279,6 +267,14 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop() * backGestureSlop;
}
+ private void onNavigationSettingsChanged() {
+ boolean wasBackAllowed = isHandlingGestures();
+ updateCurrentUserResources();
+ if (wasBackAllowed != isHandlingGestures()) {
+ mStateChangeCallback.run();
+ }
+ }
+
@Override
public void onUserSwitched(int newUserId) {
updateIsEnabled();
@@ -290,13 +286,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
*/
public void onNavBarAttached() {
mIsAttached = true;
- updatedFixedRotation();
- if (mFixedRotationFlagEnabled) {
- setRotationCallbacks(true);
- }
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(FIXED_ROTATION_TRANSFORM_SETTING_NAME),
- false /* notifyForDescendants */, mFixedRotationObserver, UserHandle.USER_ALL);
+ mOverviewProxyService.addCallback(mQuickSwitchListener);
updateIsEnabled();
startTracking();
}
@@ -306,22 +296,11 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
*/
public void onNavBarDetached() {
mIsAttached = false;
- if (mFixedRotationFlagEnabled) {
- setRotationCallbacks(false);
- }
- mContext.getContentResolver().unregisterContentObserver(mFixedRotationObserver);
+ mOverviewProxyService.removeCallback(mQuickSwitchListener);
updateIsEnabled();
stopTracking();
}
- private void setRotationCallbacks(boolean enable) {
- if (enable) {
- mOverviewProxyService.addCallback(mQuickSwitchListener);
- } else {
- mOverviewProxyService.removeCallback(mQuickSwitchListener);
- }
- }
-
/**
* @see NavigationModeController.ModeChangedListener#onNavigationModeChanged
*/
@@ -641,17 +620,6 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
- private void updatedFixedRotation() {
- boolean oldFlag = mFixedRotationFlagEnabled;
- mFixedRotationFlagEnabled = Settings.Global.getInt(mContext.getContentResolver(),
- FIXED_ROTATION_TRANSFORM_SETTING_NAME, 0) != 0;
- if (oldFlag == mFixedRotationFlagEnabled) {
- return;
- }
-
- setRotationCallbacks(mFixedRotationFlagEnabled);
- }
-
public void setInsets(int leftInset, int rightInset) {
mLeftInset = leftInset;
mRightInset = rightInset;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index df121f0faaf9..27daf8615a31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -25,6 +25,7 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -152,8 +153,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
private static final String EXTRA_APPEARANCE = "appearance";
private static final String EXTRA_TRANSIENT_STATE = "transient_state";
- private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform";
-
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -221,13 +220,13 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
* original handle hidden and we'll flip the visibilities once the
* {@link #mTasksFrozenListener} fires
*/
- private VerticalNavigationHandle mOrientationHandle;
+ private QuickswitchOrientedNavHandle mOrientationHandle;
private WindowManager.LayoutParams mOrientationParams;
- private int mStartingQuickSwitchRotation;
+ private int mStartingQuickSwitchRotation = -1;
private int mCurrentRotation;
- private boolean mFixedRotationEnabled;
private ViewTreeObserver.OnGlobalLayoutListener mOrientationHandleGlobalLayoutListener;
private UiEventLogger mUiEventLogger;
+ private boolean mShowOrientedHandleForImmersiveMode;
@com.android.internal.annotations.VisibleForTesting
public enum NavBarActionEvent implements UiEventLogger.UiEventEnum {
@@ -299,6 +298,9 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
@Override
public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {
mStartingQuickSwitchRotation = rotation;
+ if (rotation == -1) {
+ mShowOrientedHandleForImmersiveMode = false;
+ }
orientSecondaryHomeHandle();
}
@@ -370,14 +372,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
};
- private final ContentObserver mFixedRotationObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- updatedFixedRotation();
- }
- };
-
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -439,10 +433,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(FIXED_ROTATION_TRANSFORM_SETTING_NAME),
- false /* notifyForDescendants */, mFixedRotationObserver, UserHandle.USER_ALL);
-
if (savedInstanceState != null) {
mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
@@ -468,7 +458,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mNavigationModeController.removeListener(this);
mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
mContentResolver.unregisterContentObserver(mAssistContentObserver);
- mContentResolver.unregisterContentObserver(mFixedRotationObserver);
DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
}
@@ -499,7 +488,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
mNavigationBarView.setNavigationIconHints(mNavigationIconHints);
mNavigationBarView.setWindowVisible(isNavBarWindowVisible());
- updatedFixedRotation();
prepareNavigationBarView();
checkNavBarModes();
@@ -602,7 +590,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
getContext().getSystemService(DisplayManager.class)
.registerDisplayListener(this, new Handler(Looper.getMainLooper()));
- mOrientationHandle = new VerticalNavigationHandle(getContext());
+ mOrientationHandle = new QuickswitchOrientedNavHandle(getContext());
getBarTransitions().addDarkIntensityListener(mOrientationHandleIntensityListener);
mOrientationParams = new WindowManager.LayoutParams(0, 0,
@@ -613,8 +601,11 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
+ mOrientationParams.setTitle("SecondaryHomeHandle" + getContext().getDisplayId());
+ mOrientationParams.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
mWindowManager.addView(mOrientationHandle, mOrientationParams);
mOrientationHandle.setVisibility(View.GONE);
+ mOrientationParams.setFitInsetsTypes(0 /* types*/);
mOrientationHandleGlobalLayoutListener =
() -> {
if (mStartingQuickSwitchRotation == -1) {
@@ -651,22 +642,28 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
int height = 0;
int width = 0;
Rect dispSize = mWindowManager.getCurrentWindowMetrics().getBounds();
+ mOrientationHandle.setDeltaRotation(deltaRotation);
switch (deltaRotation) {
case Surface.ROTATION_90:
case Surface.ROTATION_270:
height = dispSize.height();
- width = getResources()
- .getDimensionPixelSize(R.dimen.navigation_bar_height);
+ width = mNavigationBarView.getHeight();
break;
case Surface.ROTATION_180:
case Surface.ROTATION_0:
// TODO(b/152683657): Need to determine best UX for this
- resetSecondaryHandle();
- return;
+ if (!mShowOrientedHandleForImmersiveMode) {
+ resetSecondaryHandle();
+ return;
+ }
+ width = dispSize.width();
+ height = mNavigationBarView.getHeight();
+ break;
}
mOrientationParams.gravity =
- deltaRotation == Surface.ROTATION_90 ? Gravity.LEFT : Gravity.RIGHT;
+ deltaRotation == Surface.ROTATION_0 ? Gravity.BOTTOM :
+ (deltaRotation == Surface.ROTATION_90 ? Gravity.LEFT : Gravity.RIGHT);
mOrientationParams.height = height;
mOrientationParams.width = width;
mWindowManager.updateViewLayout(mOrientationHandle, mOrientationParams);
@@ -693,14 +690,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
return delta;
}
- private void updatedFixedRotation() {
- mFixedRotationEnabled = Settings.Global.getInt(mContentResolver,
- FIXED_ROTATION_TRANSFORM_SETTING_NAME, 0) != 0;
- if (!canShowSecondaryHandle()) {
- resetSecondaryHandle();
- }
- }
-
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
if (mNavigationBarView != null) {
@@ -768,6 +757,11 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
&& mNavigationBarWindowState != state) {
mNavigationBarWindowState = state;
updateSystemUiStateFlags(-1);
+ mShowOrientedHandleForImmersiveMode = state == WINDOW_STATE_HIDDEN;
+ if (mOrientationHandle != null
+ && mStartingQuickSwitchRotation != -1) {
+ orientSecondaryHomeHandle();
+ }
if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state));
if (mNavigationBarView != null) {
@@ -1409,7 +1403,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
private boolean canShowSecondaryHandle() {
- return mFixedRotationEnabled && mNavBarMode == NAV_BAR_MODE_GESTURAL;
+ return mNavBarMode == NAV_BAR_MODE_GESTURAL;
}
private final Consumer<Integer> mRotationWatcher = rotation -> {
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 06484a226165..1eab427b4155 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -74,6 +74,7 @@ import com.android.systemui.recents.RecentsOnboarding;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
@@ -325,8 +326,8 @@ public class NavigationBarView extends FrameLayout implements
mNavColorSampleMargin = getResources()
.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
- mEdgeBackGestureHandler = new EdgeBackGestureHandler(
- context, mOverviewProxyService, mSysUiFlagContainer, mPluginManager);
+ mEdgeBackGestureHandler = new EdgeBackGestureHandler(context, mOverviewProxyService,
+ mSysUiFlagContainer, mPluginManager, this::updateStates);
mRegionSamplingHelper = new RegionSamplingHelper(this,
new RegionSamplingHelper.SamplingCallback() {
@Override
@@ -372,6 +373,11 @@ public class NavigationBarView extends FrameLayout implements
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
+ if (isGesturalMode(mNavBarMode) && mImeVisible
+ && event.getAction() == MotionEvent.ACTION_DOWN) {
+ SysUiStatsLog.write(SysUiStatsLog.IME_TOUCH_REPORTED,
+ (int) event.getX(), (int) event.getY());
+ }
return shouldDeadZoneConsumeTouchEvents(event) || super.onInterceptTouchEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index e720d820fd76..f2eec39ed17e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -443,6 +443,7 @@ public class NotificationPanelViewController extends PanelViewController {
*/
private boolean mDelayShowingKeyguardStatusBar;
+ private boolean mAnimatingQS;
private int mOldLayoutDirection;
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
@@ -1860,6 +1861,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void onAnimationEnd(Animator animation) {
+ mAnimatingQS = false;
notifyExpandingFinished();
mNotificationStackScroller.resetCheckSnoozeLeavebehind();
mQsExpansionAnimator = null;
@@ -1868,6 +1870,9 @@ public class NotificationPanelViewController extends PanelViewController {
}
}
});
+ // Let's note that we're animating QS. Moving the animator here will cancel it immediately,
+ // so we need a separate flag.
+ mAnimatingQS = true;
animator.start();
mQsExpansionAnimator = animator;
mQsAnimatorExpand = expanding;
@@ -2220,6 +2225,9 @@ public class NotificationPanelViewController extends PanelViewController {
mNotificationStackScroller.onExpansionStarted();
mIsExpanding = true;
mQsExpandedWhenExpandingStarted = mQsFullyExpanded;
+ mMediaHierarchyManager.setCollapsingShadeFromQS(mQsExpandedWhenExpandingStarted &&
+ /* We also start expanding when flinging closed Qs. Let's exclude that */
+ !mAnimatingQS);
if (mQsExpanded) {
onQsExpansionStarted();
}
@@ -2236,6 +2244,7 @@ public class NotificationPanelViewController extends PanelViewController {
mHeadsUpManager.onExpandingFinished();
mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed());
mIsExpanding = false;
+ mMediaHierarchyManager.setCollapsingShadeFromQS(false);
if (isFullyCollapsed()) {
DejankUtils.postAfterTraversal(new Runnable() {
@Override
@@ -2397,8 +2406,8 @@ public class NotificationPanelViewController extends PanelViewController {
}
@Override
- protected int getClearAllHeight() {
- return mNotificationStackScroller.getFooterViewHeight();
+ protected int getClearAllHeightWithPadding() {
+ return mNotificationStackScroller.getFooterViewHeightWithPadding();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index a902e1b0c960..caddc4a874f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -537,9 +537,9 @@ public abstract class PanelViewController {
// the animation only to the last notification, and then jump to the maximum panel height so
// clear all just fades in and the decelerating motion is towards the last notification.
final boolean clearAllExpandHack = expand &&
- shouldExpandToTopOfClearAll(getMaxPanelHeight() - getClearAllHeight());
+ shouldExpandToTopOfClearAll(getMaxPanelHeight() - getClearAllHeightWithPadding());
if (clearAllExpandHack) {
- target = getMaxPanelHeight() - getClearAllHeight();
+ target = getMaxPanelHeight() - getClearAllHeightWithPadding();
}
if (target == mExpandedHeight || getOverExpansionAmount() > 0f && expand) {
notifyExpandingFinished();
@@ -1030,9 +1030,9 @@ public abstract class PanelViewController {
protected abstract boolean isClearAllVisible();
/**
- * @return the height of the clear all button, in pixels
+ * @return the height of the clear all button, in pixels including padding
*/
- protected abstract int getClearAllHeight();
+ protected abstract int getClearAllHeightWithPadding();
public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
mHeadsUpManager = headsUpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickswitchOrientedNavHandle.java
index 0cdf1d32d6a0..fe74677a8d51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickswitchOrientedNavHandle.java
@@ -19,19 +19,25 @@ package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.RectF;
+import android.view.Surface;
import com.android.systemui.R;
/** Temporarily shown view when using QuickSwitch to switch between apps of different rotations */
-public class VerticalNavigationHandle extends NavigationHandle {
+public class QuickswitchOrientedNavHandle extends NavigationHandle {
private final int mWidth;
private final RectF mTmpBoundsRectF = new RectF();
+ private @Surface.Rotation int mDeltaRotation;
- public VerticalNavigationHandle(Context context) {
+ public QuickswitchOrientedNavHandle(Context context) {
super(context);
mWidth = context.getResources().getDimensionPixelSize(R.dimen.navigation_home_handle_width);
}
+ void setDeltaRotation(@Surface.Rotation int rotation) {
+ mDeltaRotation = rotation;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
canvas.drawRoundRect(computeHomeHandleBounds(), mRadius, mRadius, mPaint);
@@ -42,12 +48,32 @@ public class VerticalNavigationHandle extends NavigationHandle {
int top;
int bottom;
int right;
- int topStart = getLocationOnScreen()[1];
int radiusOffset = mRadius * 2;
- right = getWidth() - mBottom;
- top = getHeight() / 2 - (mWidth / 2) - (topStart / 2);
- left = getWidth() - mBottom - radiusOffset;
- bottom = top + mWidth;
+ int topStart = getLocationOnScreen()[1];
+
+ switch (mDeltaRotation) {
+ default:
+ case Surface.ROTATION_0:
+ case Surface.ROTATION_180:
+ int height = mRadius * 2;
+ left = getWidth() / 2 - mWidth / 2;
+ top = (getHeight() - mBottom - height);
+ right = getWidth() / 2 + mWidth / 2;
+ bottom = top + height;
+ break;
+ case Surface.ROTATION_90:
+ left = mBottom;
+ right = left + radiusOffset;
+ top = getHeight() / 2 - (mWidth / 2) - (topStart / 2);
+ bottom = top + mWidth;
+ break;
+ case Surface.ROTATION_270:
+ right = getWidth() - mBottom;
+ left = right - radiusOffset;
+ top = getHeight() / 2 - (mWidth / 2) - (topStart / 2);
+ bottom = top + mWidth;
+ break;
+ }
mTmpBoundsRectF.set(left, top, right, bottom);
return mTmpBoundsRectF;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 3df1c11bc044..6bc0565510a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -72,9 +72,6 @@ public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
-
- // Creating AudioRecordingDisclosureBar and just letting it run
- new AudioRecordingDisclosureBar(mContext);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index 8b85a0961463..36e360da857f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -99,9 +99,10 @@ public class AudioRecordingDisclosureBar implements
private View mIconTextsContainer;
private View mIconContainerBg;
private View mIcon;
- private View mBgRight;
+ private View mBgEnd;
private View mTextsContainers;
private TextView mTextView;
+ private boolean mIsLtr;
@State private int mState = STATE_NOT_SHOWN;
@@ -232,6 +233,9 @@ public class AudioRecordingDisclosureBar implements
Log.d(TAG, "Showing indicator for " + packageName + " (" + label + ")...");
}
+ mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR;
+
// Inflate the indicator view
mIndicatorView = LayoutInflater.from(mContext).inflate(
R.layout.tv_audio_recording_indicator,
@@ -241,7 +245,17 @@ public class AudioRecordingDisclosureBar implements
mIcon = mIconTextsContainer.findViewById(R.id.icon_mic);
mTextsContainers = mIconTextsContainer.findViewById(R.id.texts_container);
mTextView = mTextsContainers.findViewById(R.id.text);
- mBgRight = mIndicatorView.findViewById(R.id.bg_right);
+ mBgEnd = mIndicatorView.findViewById(R.id.bg_end);
+
+ // Swap background drawables depending on layout directions (both drawables have rounded
+ // corners only on one side)
+ if (mIsLtr) {
+ mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
+ mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
+ } else {
+ mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded);
+ mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded);
+ }
// Set up the notification text
mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
@@ -261,7 +275,8 @@ public class AudioRecordingDisclosureBar implements
// Now that the width of the indicator has been assigned, we can
// move it in from off the screen.
- final int initialOffset = mIndicatorView.getWidth();
+ final int initialOffset =
+ (mIsLtr ? 1 : -1) * mIndicatorView.getWidth();
final AnimatorSet set = new AnimatorSet();
set.setDuration(ANIMATION_DURATION);
set.playTogether(
@@ -294,7 +309,7 @@ public class AudioRecordingDisclosureBar implements
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
- layoutParams.gravity = Gravity.TOP | Gravity.RIGHT;
+ layoutParams.gravity = Gravity.TOP | (mIsLtr ? Gravity.RIGHT : Gravity.LEFT);
layoutParams.setTitle(LAYOUT_PARAMS_TITLE);
layoutParams.packageName = mContext.getPackageName();
final WindowManager windowManager = (WindowManager) mContext.getSystemService(
@@ -317,7 +332,7 @@ public class AudioRecordingDisclosureBar implements
ObjectAnimator.ofFloat(mIconTextsContainer, View.TRANSLATION_X, 0),
ObjectAnimator.ofFloat(mIconContainerBg, View.ALPHA, 1f),
ObjectAnimator.ofFloat(mTextsContainers, View.ALPHA, 1f),
- ObjectAnimator.ofFloat(mBgRight, View.ALPHA, 1f));
+ ObjectAnimator.ofFloat(mBgEnd, View.ALPHA, 1f));
set.setDuration(ANIMATION_DURATION);
set.addListener(
new AnimatorListenerAdapter() {
@@ -334,13 +349,13 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void minimize() {
if (DEBUG) Log.d(TAG, "Minimizing...");
- final int targetOffset = mTextsContainers.getWidth();
+ final int targetOffset = (mIsLtr ? 1 : -1) * mTextsContainers.getWidth();
final AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(mIconTextsContainer, View.TRANSLATION_X, targetOffset),
ObjectAnimator.ofFloat(mIconContainerBg, View.ALPHA, 0f),
ObjectAnimator.ofFloat(mTextsContainers, View.ALPHA, 0f),
- ObjectAnimator.ofFloat(mBgRight, View.ALPHA, 0f));
+ ObjectAnimator.ofFloat(mBgEnd, View.ALPHA, 0f));
set.setDuration(ANIMATION_DURATION);
set.addListener(
new AnimatorListenerAdapter() {
@@ -357,8 +372,8 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void hide() {
if (DEBUG) Log.d(TAG, "Hiding...");
- final int targetOffset =
- mIndicatorView.getWidth() - (int) mIconTextsContainer.getTranslationX();
+ final int targetOffset = (mIsLtr ? 1 : -1) * (mIndicatorView.getWidth()
+ - (int) mIconTextsContainer.getTranslationX());
final AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(mIndicatorView, View.TRANSLATION_X, targetOffset),
@@ -411,7 +426,7 @@ public class AudioRecordingDisclosureBar implements
mIcon = null;
mTextsContainers = null;
mTextView = null;
- mBgRight = null;
+ mBgEnd = null;
mState = STATE_NOT_SHOWN;
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
index e5b126d7ff7f..3c0a23aa2eca 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
@@ -150,15 +150,10 @@ class TransitionLayout @JvmOverloads constructor(
}
override fun dispatchDraw(canvas: Canvas?) {
- val clip = !boundsRect.isEmpty
- if (clip) {
- canvas?.save()
- canvas?.clipRect(boundsRect)
- }
+ canvas?.save()
+ canvas?.clipRect(boundsRect)
super.dispatchDraw(canvas)
- if (clip) {
- canvas?.restore()
- }
+ canvas?.restore()
}
private fun updateBounds() {
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
index b73aeb30009c..5143e429768e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
@@ -46,6 +46,9 @@ open class TransitionLayoutController {
private var state = TransitionViewState()
private var pivot = PointF()
private var animator: ValueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f)
+ private var currentHeight: Int = 0
+ private var currentWidth: Int = 0
+ var sizeChangedListener: ((Int, Int) -> Unit)? = null
init {
animator.apply {
@@ -67,7 +70,16 @@ open class TransitionLayoutController {
progress = animator.animatedFraction,
pivot = pivot,
resultState = currentState)
- view.setState(currentState)
+ applyStateToLayout(currentState)
+ }
+
+ private fun applyStateToLayout(state: TransitionViewState) {
+ transitionLayout?.setState(state)
+ if (currentHeight != state.height || currentWidth != state.width) {
+ currentHeight = state.height
+ currentWidth = state.width
+ sizeChangedListener?.invoke(currentWidth, currentHeight)
+ }
}
/**
@@ -213,7 +225,7 @@ open class TransitionLayoutController {
this.state = state.copy()
if (applyImmediately || transitionLayout == null) {
animator.cancel()
- transitionLayout?.setState(this.state)
+ applyStateToLayout(this.state)
currentState = state.copy(reusedState = currentState)
} else if (animated) {
animationStartState = currentState.copy()
@@ -221,7 +233,7 @@ open class TransitionLayoutController {
animator.startDelay = delay
animator.start()
} else if (!animator.isRunning) {
- transitionLayout?.setState(this.state)
+ applyStateToLayout(this.state)
currentState = state.copy(reusedState = currentState)
}
// otherwise the desired state was updated and the animation will go to the new target
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt b/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
index 5b6444d8feaf..d6e7a8b28f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
@@ -70,7 +70,10 @@ class UniqueObjectHostView(
}
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
- if (child?.measuredWidth == 0 || measuredWidth == 0 || child?.requiresRemeasuring == true) {
+ if (child == null) {
+ throw IllegalArgumentException("child must be non-null")
+ }
+ if (child.measuredWidth == 0 || measuredWidth == 0 || child.requiresRemeasuring == true) {
super.addView(child, index, params)
return
}
@@ -78,11 +81,13 @@ class UniqueObjectHostView(
// right size when being attached to this view
invalidate()
addViewInLayout(child, index, params, true /* preventRequestLayout */)
+ // RTL properties are normally resolved in onMeasure(), which we are intentionally skipping
+ child.resolveRtlPropertiesIfNeeded()
val left = paddingLeft
val top = paddingTop
val paddingHorizontal = paddingStart + paddingEnd
val paddingVertical = paddingTop + paddingBottom
- child!!.layout(left,
+ child.layout(left,
top,
left + measuredWidth - paddingHorizontal,
top + measuredHeight - paddingVertical)
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index 6794a2a3f72f..52d46476df83 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -253,7 +253,7 @@ public class ProximitySensor {
private final AtomicBoolean mRegistered = new AtomicBoolean();
@Inject
- public ProximityCheck(ProximitySensor sensor, DelayableExecutor delayableExecutor) {
+ public ProximityCheck(ProximitySensor sensor, @Main DelayableExecutor delayableExecutor) {
mSensor = sensor;
mSensor.setTag("prox_check");
mDelayableExecutor = delayableExecutor;
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
index 7b114525adcd..8ba5b9951c54 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
@@ -56,12 +56,14 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
private static final boolean DEBUG = false;
+ // NOTE: All these constants came from InsetsController.
public static final int ANIMATION_DURATION_SHOW_MS = 275;
public static final int ANIMATION_DURATION_HIDE_MS = 340;
public static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
private static final int DIRECTION_NONE = 0;
private static final int DIRECTION_SHOW = 1;
private static final int DIRECTION_HIDE = 2;
+ private static final int FLOATING_IME_BOTTOM_INSET = -80;
SystemWindows mSystemWindows;
final Handler mHandler;
@@ -271,8 +273,16 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
// Set frame, but only if the new frame isn't empty -- this maintains continuity
final Rect newFrame = imeSource.getFrame();
- if (newFrame.height() != 0) {
+ mImeFrame.set(newFrame);
+ final boolean isFloating = newFrame.height() == 0;
+ if (isFloating) {
+ // This is likely a "floating" or "expanded" IME, so to get animations, just
+ // pretend the ime has some size just below the screen.
mImeFrame.set(newFrame);
+ final int floatingInset = (int) (
+ mSystemWindows.mDisplayController.getDisplayLayout(mDisplayId).density()
+ * FLOATING_IME_BOTTOM_INSET);
+ mImeFrame.bottom -= floatingInset;
}
if (DEBUG) {
Slog.d(TAG, "Run startAnim show:" + show + " was:"
@@ -316,6 +326,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
SurfaceControl.Transaction t = mTransactionPool.acquire();
float value = (float) animation.getAnimatedValue();
t.setPosition(mImeSourceControl.getLeash(), x, value);
+ final float alpha = isFloating ? (value - hiddenY) / (shownY - hiddenY) : 1.f;
+ t.setAlpha(mImeSourceControl.getLeash(), alpha);
dispatchPositionChanged(mDisplayId, imeTop(value), t);
t.apply();
mTransactionPool.release(t);
@@ -327,6 +339,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
public void onAnimationStart(Animator animation) {
SurfaceControl.Transaction t = mTransactionPool.acquire();
t.setPosition(mImeSourceControl.getLeash(), x, startY);
+ final float alpha = isFloating ? (startY - hiddenY) / (shownY - hiddenY) : 1.f;
+ t.setAlpha(mImeSourceControl.getLeash(), alpha);
if (DEBUG) {
Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
+ imeTop(hiddenY) + "->" + imeTop(shownY)
@@ -351,6 +365,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
SurfaceControl.Transaction t = mTransactionPool.acquire();
if (!mCancelled) {
t.setPosition(mImeSourceControl.getLeash(), x, endY);
+ t.setAlpha(mImeSourceControl.getLeash(), 1.f);
}
dispatchEndPositioning(mDisplayId, mCancelled, t);
if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 73aaeffd6044..1cdc02fdd01a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -41,12 +41,10 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.FakeProximitySensor;
import com.android.systemui.util.sensors.FakeSensorManager;
import com.android.systemui.util.sensors.ProximitySensor;
-import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.wakelock.WakeLock;
import com.android.systemui.util.wakelock.WakeLockFake;
@@ -72,11 +70,12 @@ public class DozeTriggersTest extends SysuiTestCase {
private BroadcastDispatcher mBroadcastDispatcher;
@Mock
private DockManager mDockManager;
+ @Mock
+ private ProximitySensor.ProximityCheck mProximityCheck;
private DozeTriggers mTriggers;
private FakeSensorManager mSensors;
private Sensor mTapSensor;
private FakeProximitySensor mProximitySensor;
- private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() throws Exception {
@@ -91,8 +90,8 @@ public class DozeTriggersTest extends SysuiTestCase {
mProximitySensor = new FakeProximitySensor(getContext().getResources(), asyncSensorManager);
mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, config, parameters,
- asyncSensorManager, mFakeExecutor, wakeLock, true,
- mDockManager, mProximitySensor, mock(DozeLog.class), mBroadcastDispatcher);
+ asyncSensorManager, wakeLock, true, mDockManager, mProximitySensor,
+ mProximityCheck, mock(DozeLog.class), mBroadcastDispatcher);
waitForSensorManager();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
index 8b254e3a2df0..58959c456cd9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.globalactions;
import static android.view.WindowInsets.Type.ime;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -39,6 +40,7 @@ import androidx.test.rule.ActivityTestRule;
import com.android.systemui.SysuiTestCase;
+import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
@@ -52,6 +54,11 @@ public class GlobalActionsImeTest extends SysuiTestCase {
public ActivityTestRule<TestActivity> mActivityTestRule = new ActivityTestRule<>(
TestActivity.class, false, false);
+ @After
+ public void tearDown() {
+ executeShellCommand("input keyevent HOME");
+ }
+
/**
* This test verifies that GlobalActions, which is frequently used to capture bugreports,
* doesn't interfere with the IME, i.e. soft-keyboard state.
@@ -68,6 +75,9 @@ public class GlobalActionsImeTest extends SysuiTestCase {
waitUntil("Ime is not visible", activity::isImeVisible);
}
+ // In some cases, IME is not controllable. e.g., floating IME or fullscreen IME.
+ final boolean activityControlledIme = activity.mControlsIme;
+
executeShellCommand("input keyevent --longpress POWER");
waitUntil("activity loses focus", () -> !activity.mHasFocus);
@@ -77,9 +87,9 @@ public class GlobalActionsImeTest extends SysuiTestCase {
runAssertionOnMainThread(() -> {
assertTrue("IME should remain visible behind GlobalActions, but didn't",
- activity.mControlsIme);
- assertTrue("App behind GlobalActions should remain in control of IME, but didn't",
activity.mImeVisible);
+ assertEquals("App behind GlobalActions should remain in control of IME, but didn't",
+ activityControlledIme, activity.mControlsIme);
});
}
@@ -181,7 +191,7 @@ public class GlobalActionsImeTest extends SysuiTestCase {
}
boolean isImeVisible() {
- return mHasFocus && mControlsIme && mImeVisible;
+ return mHasFocus && mImeVisible;
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
index 9aee11e4924f..008dc12bba03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
@@ -27,6 +27,7 @@ import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.MediaHeaderView
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.util.mockito.capture
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -94,7 +95,7 @@ class KeyguardMediaControllerTest : SysuiTestCase() {
private fun triggerVisibilityListener() {
keyguardMediaController.attach(mediaHeaderView)
- verify(mediaHost).visibleChangedListener = visibilityListener.capture()
+ verify(mediaHost).addVisibilityChangeListener(capture(visibilityListener))
visibilityListener.value.invoke(true)
}
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index a297f32b9c34..b7f317b38743 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -242,4 +242,15 @@ public class MediaControlPanelTest : SysuiTestCase() {
assertThat(seamlessText.getText()).isEqualTo(context.getResources().getString(
com.android.internal.R.string.ext_media_seamless_action))
}
+
+ @Test
+ fun bindDeviceResumptionPlayer() {
+ player.attach(holder)
+ val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+ emptyList(), PACKAGE, session.getSessionToken(), null, device, true, null,
+ resumption = true)
+ player.bind(state)
+ assertThat(seamlessText.getText()).isEqualTo(DEVICE_NAME)
+ assertThat(seamless.isEnabled()).isFalse()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
index 618ee892b2b0..9fdd9ad744ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
@@ -79,8 +79,8 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
mManager.addListener(mListener);
mMediaData = new MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null,
- new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, KEY,
- false);
+ new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, false,
+ KEY, false);
mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index 54520be8a03f..e56bbabfdc0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -1,6 +1,11 @@
package com.android.systemui.media
-import android.app.Notification
+import android.app.Notification.MediaStyle
+import android.app.PendingIntent
+import android.media.MediaDescription
+import android.media.MediaMetadata
+import android.media.session.MediaController
+import android.media.session.MediaSession
import android.service.notification.StatusBarNotification
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -8,6 +13,10 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.SbnBuilder
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -19,13 +28,14 @@ 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 const val APP_NAME = "SystemUI"
+private const val SESSION_ARTIST = "artist"
+private const val SESSION_TITLE = "title"
-private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
private fun <T> anyObject(): T {
return Mockito.anyObject<T>()
}
@@ -36,33 +46,47 @@ private fun <T> anyObject(): T {
class MediaDataManagerTest : SysuiTestCase() {
@Mock lateinit var mediaControllerFactory: MediaControllerFactory
- @Mock lateinit var backgroundExecutor: Executor
- @Mock lateinit var foregroundExecutor: Executor
+ @Mock lateinit var controller: MediaController
+ lateinit var session: MediaSession
+ lateinit var metadataBuilder: MediaMetadata.Builder
+ lateinit var backgroundExecutor: FakeExecutor
+ lateinit var foregroundExecutor: FakeExecutor
@Mock lateinit var dumpManager: DumpManager
@Mock lateinit var broadcastDispatcher: BroadcastDispatcher
@Mock lateinit var mediaTimeoutListener: MediaTimeoutListener
@Mock lateinit var mediaResumeListener: MediaResumeListener
+ @Mock lateinit var pendingIntent: PendingIntent
@JvmField @Rule val mockito = MockitoJUnit.rule()
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
@Before
fun setup() {
+ foregroundExecutor = FakeExecutor(FakeSystemClock())
+ backgroundExecutor = FakeExecutor(FakeSystemClock())
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
+ session = MediaSession(context, "MediaDataManagerTestSession")
+ mediaNotification = SbnBuilder().run {
+ setPkg(PACKAGE_NAME)
+ modifyNotification(context).also {
+ it.setSmallIcon(android.R.drawable.ic_media_pause)
+ it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+ }
+ build()
+ }
+ metadataBuilder = MediaMetadata.Builder().apply {
+ putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
+ putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
+ }
+ whenever(mediaControllerFactory.create(eq(session.sessionToken))).thenReturn(controller)
}
@After
fun tearDown() {
+ session.release()
mediaDataManager.destroy()
}
@@ -80,9 +104,22 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testOnSwipeToDismiss_deactivatesMedia() {
+ val data = MediaData(initialized = true, backgroundColor = 0, app = null, appIcon = null,
+ artist = null, song = null, artwork = null, actions = emptyList(),
+ actionsToShowInCompact = emptyList(), packageName = "INVALID", token = null,
+ clickIntent = null, device = null, active = true, resumeAction = null)
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = data)
+
+ mediaDataManager.onSwipeToDismiss()
+ assertThat(data.active).isFalse()
+ }
+
+ @Test
fun testLoadsMetadataOnBackground() {
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
- verify(backgroundExecutor).execute(anyObject())
+ assertThat(backgroundExecutor.numPending()).isEqualTo(1)
}
@Test
@@ -95,6 +132,30 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testOnMetaDataLoaded_conservesActiveFlag() {
+ val listener = TestListener()
+ whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
+ mediaDataManager.addListener(listener)
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(listener.data!!.active).isTrue()
+
+ // Swiping away makes the notification not active
+ mediaDataManager.onSwipeToDismiss()
+ assertThat(mediaDataManager.hasActiveMedia()).isFalse()
+
+ // And when a notification is updated
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+
+ // MediaData should still be inactive
+ assertThat(mediaDataManager.hasActiveMedia()).isFalse()
+ }
+
+ @Test
fun testHasAnyMedia_whenAddingMedia() {
assertThat(mediaDataManager.hasAnyMedia()).isFalse()
val data = mock(MediaData::class.java)
@@ -123,4 +184,66 @@ class MediaDataManagerTest : SysuiTestCase() {
verify(listener).onMediaDataRemoved(eq(KEY))
}
-} \ No newline at end of file
+
+ @Test
+ fun testOnNotificationRemoved_withResumption() {
+ // GIVEN that the manager has a notification with a resume action
+ val listener = TestListener()
+ mediaDataManager.addListener(listener)
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+ val data = listener.data!!
+ assertThat(data.resumption).isFalse()
+ mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
+ // WHEN the notification is removed
+ mediaDataManager.onNotificationRemoved(KEY)
+ // THEN the media data indicates that it is
+ assertThat(listener.data!!.resumption).isTrue()
+ }
+
+ @Test
+ fun testAddResumptionControls() {
+ val listener = TestListener()
+ mediaDataManager.addListener(listener)
+ // WHEN resumption controls are added`
+ val desc = MediaDescription.Builder().run {
+ setTitle(SESSION_TITLE)
+ build()
+ }
+ mediaDataManager.addResumptionControls(desc, Runnable {}, session.sessionToken, APP_NAME,
+ pendingIntent, PACKAGE_NAME)
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+ // THEN the media data indicates that it is for resumption
+ val data = listener.data!!
+ assertThat(data.resumption).isTrue()
+ assertThat(data.song).isEqualTo(SESSION_TITLE)
+ assertThat(data.app).isEqualTo(APP_NAME)
+ assertThat(data.actions).hasSize(1)
+ }
+
+ /**
+ * Simple implementation of [MediaDataManager.Listener] for the test.
+ *
+ * Giving up on trying to get a mock Listener and ArgumentCaptor to work.
+ */
+ private class TestListener : MediaDataManager.Listener {
+ var data: MediaData? = null
+ var key: String? = null
+ var oldKey: String? = null
+
+ override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
+ this.key = key
+ this.oldKey = oldKey
+ this.data = data
+ }
+
+ override fun onMediaDataRemoved(key: String) {
+ this.key = key
+ oldKey = null
+ data = null
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
index c9e6f55ff59a..91c5ff8ee627 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
@@ -70,7 +70,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
@Mock
private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
@Mock
- private lateinit var mediaViewManager: MediaViewManager
+ private lateinit var mediaCarouselController: MediaCarouselController
@Mock
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Captor
@@ -82,13 +82,13 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
@Before
fun setup() {
- `when`(mediaViewManager.mediaFrame).thenReturn(mediaFrame)
+ `when`(mediaCarouselController.mediaFrame).thenReturn(mediaFrame)
mediaHiearchyManager = MediaHierarchyManager(
context,
statusBarStateController,
keyguardStateController,
bypassController,
- mediaViewManager,
+ mediaCarouselController,
notificationLockscreenUserManager,
wakefulnessLifecycle)
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
@@ -97,7 +97,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS)
`when`(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
// We'll use the viewmanager to verify a few calls below, let's reset this.
- clearInvocations(mediaViewManager)
+ clearInvocations(mediaCarouselController)
}
@@ -118,14 +118,14 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
fun testBlockedWhenScreenTurningOff() {
// Let's set it onto QS:
mediaHiearchyManager.qsExpansion = 1.0f
- verify(mediaViewManager).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+ verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
val observer = wakefullnessObserver.value
assertNotNull("lifecycle observer wasn't registered", observer)
observer.onStartedGoingToSleep()
- clearInvocations(mediaViewManager)
+ clearInvocations(mediaCarouselController)
mediaHiearchyManager.qsExpansion = 0.0f
- verify(mediaViewManager, times(0)).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+ verify(mediaCarouselController, times(0)).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
}
@@ -133,13 +133,13 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
fun testAllowedWhenNotTurningOff() {
// Let's set it onto QS:
mediaHiearchyManager.qsExpansion = 1.0f
- verify(mediaViewManager).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+ verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
val observer = wakefullnessObserver.value
assertNotNull("lifecycle observer wasn't registered", observer)
- clearInvocations(mediaViewManager)
+ clearInvocations(mediaCarouselController)
mediaHiearchyManager.qsExpansion = 0.0f
- verify(mediaViewManager).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+ verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
}
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
index 75018df023cc..e9a0a40fe8ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
@@ -22,6 +22,7 @@ import android.view.View
import android.widget.SeekBar
import android.widget.TextView
import androidx.test.filters.SmallTest
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -36,6 +37,9 @@ import org.mockito.Mockito.`when` as whenever
@TestableLooper.RunWithLooper
public class SeekBarObserverTest : SysuiTestCase() {
+ private val disabledHeight = 1
+ private val enabledHeight = 2
+
private lateinit var observer: SeekBarObserver
@Mock private lateinit var mockHolder: PlayerViewHolder
private lateinit var seekBarView: SeekBar
@@ -45,12 +49,19 @@ public class SeekBarObserverTest : SysuiTestCase() {
@Before
fun setUp() {
mockHolder = mock(PlayerViewHolder::class.java)
+
+ context.orCreateTestableResources
+ .addOverride(R.dimen.qs_media_enabled_seekbar_height, enabledHeight)
+ context.orCreateTestableResources
+ .addOverride(R.dimen.qs_media_disabled_seekbar_height, disabledHeight)
+
seekBarView = SeekBar(context)
elapsedTimeView = TextView(context)
totalTimeView = TextView(context)
whenever(mockHolder.seekBar).thenReturn(seekBarView)
whenever(mockHolder.elapsedTimeView).thenReturn(elapsedTimeView)
whenever(mockHolder.totalTimeView).thenReturn(totalTimeView)
+
observer = SeekBarObserver(mockHolder)
}
@@ -60,11 +71,12 @@ public class SeekBarObserverTest : SysuiTestCase() {
val isEnabled = false
val data = SeekBarViewModel.Progress(isEnabled, false, null, null)
observer.onChanged(data)
- // THEN seek bar shows just a line with no text
+ // THEN seek bar shows just a thin line with no text
assertThat(seekBarView.isEnabled()).isFalse()
assertThat(seekBarView.getThumb().getAlpha()).isEqualTo(0)
assertThat(elapsedTimeView.getText()).isEqualTo("")
assertThat(totalTimeView.getText()).isEqualTo("")
+ assertThat(seekBarView.maxHeight).isEqualTo(disabledHeight)
}
@Test
@@ -73,10 +85,11 @@ public class SeekBarObserverTest : SysuiTestCase() {
val isEnabled = true
val data = SeekBarViewModel.Progress(isEnabled, true, 3000, 12000)
observer.onChanged(data)
- // THEN seek bar is visible
+ // THEN seek bar is visible and thick
assertThat(seekBarView.getVisibility()).isEqualTo(View.VISIBLE)
assertThat(elapsedTimeView.getVisibility()).isEqualTo(View.VISIBLE)
assertThat(totalTimeView.getVisibility()).isEqualTo(View.VISIBLE)
+ assertThat(seekBarView.maxHeight).isEqualTo(enabledHeight)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 1c0d451e064a..438de99015a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -14,6 +14,10 @@
package com.android.systemui.qs.tileimpl;
+
+import static androidx.lifecycle.Lifecycle.State.DESTROYED;
+import static androidx.lifecycle.Lifecycle.State.RESUMED;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_CLICK;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_LONG_PRESS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_SECONDARY_CLICK;
@@ -23,6 +27,9 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -267,6 +274,42 @@ public class QSTileImplTest extends SysuiTestCase {
verify(mQsLogger).logTileChangeListening(SPEC, false);
}
+ @Test
+ public void testListeningTrue_stateAtLeastResumed() {
+ mTile.setListening(new Object(), true); // Listen with some object
+
+ TestableLooper.get(this).processAllMessages();
+
+ assertTrue(mTile.getLifecycle().getCurrentState().isAtLeast(RESUMED));
+ }
+
+ @Test
+ public void testTileDoesntStartResumed() {
+ assertFalse(mTile.getLifecycle().getCurrentState().isAtLeast(RESUMED));
+ }
+
+ @Test
+ public void testListeningFalse_stateAtMostCreated() {
+ Object o = new Object();
+ mTile.setListening(o, true);
+
+ mTile.setListening(o, false);
+
+ TestableLooper.get(this).processAllMessages();
+ assertFalse(mTile.getLifecycle().getCurrentState().isAtLeast(RESUMED));
+ }
+
+ @Test
+ public void testListeningFalse_stateNotDestroyed() {
+ Object o = new Object();
+ mTile.setListening(o, true);
+
+ mTile.setListening(o, false);
+
+ TestableLooper.get(this).processAllMessages();
+ assertNotEquals(DESTROYED, mTile.getLifecycle().getCurrentState());
+ }
+
private void assertEvent(UiEventLogger.UiEventEnum eventType,
UiEventLoggerFake.FakeUiEvent fakeEvent) {
assertEquals(eventType.getId(), fakeEvent.eventId);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 22f50d0fb591..e0d268127d90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
@@ -40,6 +42,7 @@ import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.UserInfo;
import android.graphics.Color;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.face.FaceManager;
@@ -79,6 +82,8 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Collections;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KeyguardIndicationControllerTest extends SysuiTestCase {
@@ -154,7 +159,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mController = new KeyguardIndicationController(mContext, mWakeLockBuilder,
mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor,
- mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats);
+ mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats,
+ mUserManager);
mController.setIndicationArea(mIndicationArea);
mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
clearInvocations(mIBatteryStats);
@@ -242,6 +248,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
@Test
public void disclosure_unmanaged() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false);
+ when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(false);
createController();
verify(mDisclosure).setVisibility(View.GONE);
@@ -249,7 +256,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
}
@Test
- public void disclosure_managedNoOwnerName() {
+ public void disclosure_deviceOwner_noOwnerName() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null);
createController();
@@ -260,6 +267,19 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
}
@Test
+ public void disclosure_orgOwnedDeviceWithManagedProfile_noOwnerName() {
+ when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(true);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(Collections.singletonList(
+ new UserInfo(10, /* name */ null, /* flags */ FLAG_MANAGED_PROFILE)));
+ when(mDevicePolicyManager.getOrganizationNameForUser(eq(10))).thenReturn(null);
+ createController();
+
+ verify(mDisclosure).setVisibility(View.VISIBLE);
+ verify(mDisclosure).switchIndication(R.string.do_disclosure_generic);
+ verifyNoMoreInteractions(mDisclosure);
+ }
+
+ @Test
public void disclosure_hiddenWhenDozing() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null);
@@ -292,7 +312,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
}
@Test
- public void disclosure_managedOwnerName() {
+ public void disclosure_deviceOwner_withOwnerName() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(ORGANIZATION_NAME);
createController();
@@ -303,6 +323,19 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
}
@Test
+ public void disclosure_orgOwnedDeviceWithManagedProfile_withOwnerName() {
+ when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(true);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(Collections.singletonList(
+ new UserInfo(10, /* name */ null, FLAG_MANAGED_PROFILE)));
+ when(mDevicePolicyManager.getOrganizationNameForUser(eq(10))).thenReturn(ORGANIZATION_NAME);
+ createController();
+
+ verify(mDisclosure).setVisibility(View.VISIBLE);
+ verify(mDisclosure).switchIndication(mDisclosureWithOrganization);
+ verifyNoMoreInteractions(mDisclosure);
+ }
+
+ @Test
public void disclosure_updateOnTheFly() {
ArgumentCaptor<BroadcastReceiver> receiver = ArgumentCaptor.forClass(
BroadcastReceiver.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 06bad80d6f87..c979dc637fde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.notification.logging;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
-
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -200,7 +198,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
assertEquals(TEST_UID, n.uid);
assertEquals(1, n.instanceId);
assertFalse(n.isGroupSummary);
- assertEquals(1 + BUCKET_ALERTING, n.section);
+ assertEquals(Notifications.Notification.SECTION_ALERTING, n.section);
}
@Test
@@ -217,7 +215,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
assertEquals(TEST_UID, n.uid);
assertEquals(1, n.instanceId);
assertFalse(n.isGroupSummary);
- assertEquals(1 + BUCKET_ALERTING, n.section);
+ assertEquals(Notifications.Notification.SECTION_ALERTING, n.section);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
index ec73a7571969..43d8b50bcf72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
@@ -49,6 +49,7 @@ import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -69,6 +70,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
private final PackageManager mMockPackageManager = mock(PackageManager.class);
private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
private StatusBarNotification mSbn;
+ private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake();
@Before
public void setUp() throws Exception {
@@ -94,7 +96,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
@Test
public void testBindNotification_SetsTextApplicationName() {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>());
final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
}
@@ -104,7 +106,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
final Drawable iconDrawable = mock(Drawable.class);
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>());
final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -120,7 +122,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
assertEquals(expectedOps, ops);
assertEquals(TEST_UID, uid);
latch.countDown();
- }, mSbn, expectedOps);
+ }, mSbn, mUiEventLogger, expectedOps);
final View settingsButton = mAppOpsInfo.findViewById(R.id.settings);
settingsButton.performClick();
@@ -129,6 +131,14 @@ public class AppOpsInfoTest extends SysuiTestCase {
}
@Test
+ public void testBindNotification_LogsOpen() throws Exception {
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>());
+ assertEquals(1, mUiEventLogger.numLogs());
+ assertEquals(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN.getId(),
+ mUiEventLogger.eventId(0));
+ }
+
+ @Test
public void testOk() {
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_CAMERA);
@@ -139,7 +149,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
assertEquals(expectedOps, ops);
assertEquals(TEST_UID, uid);
latch.countDown();
- }, mSbn, expectedOps);
+ }, mSbn, mUiEventLogger, expectedOps);
final View okButton = mAppOpsInfo.findViewById(R.id.ok);
okButton.performClick();
@@ -151,7 +161,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
public void testPrompt_camera() {
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_CAMERA);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
assertEquals("This app is using the camera.", prompt.getText());
}
@@ -160,7 +170,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
public void testPrompt_mic() {
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_RECORD_AUDIO);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
assertEquals("This app is using the microphone.", prompt.getText());
}
@@ -169,7 +179,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
public void testPrompt_overlay() {
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
assertEquals("This app is displaying over other apps on your screen.", prompt.getText());
}
@@ -179,7 +189,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_CAMERA);
expectedOps.add(OP_RECORD_AUDIO);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
assertEquals("This app is using the microphone and camera.", prompt.getText());
}
@@ -190,7 +200,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
expectedOps.add(OP_CAMERA);
expectedOps.add(OP_RECORD_AUDIO);
expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
assertEquals("This app is displaying over other apps on your screen and using"
+ " the microphone and camera.", prompt.getText());
@@ -201,7 +211,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_CAMERA);
expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
assertEquals("This app is displaying over other apps on your screen and using"
+ " the camera.", prompt.getText());
@@ -212,7 +222,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_RECORD_AUDIO);
expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
- mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
assertEquals("This app is displaying over other apps on your screen and using"
+ " the microphone.", prompt.getText());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 5b5873b7a1cf..9dee84347ae1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -64,6 +64,8 @@ import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -149,7 +151,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager,
() -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider,
mINotificationManager, mLauncherApps, mShortcutManager,
- mChannelEditorDialogController, mContextTracker, mProvider, mBubbleController);
+ mChannelEditorDialogController, mContextTracker, mProvider, mBubbleController,
+ new UiEventLoggerFake());
mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
mCheckSaveListener, mOnSettingsClickListener);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
@@ -362,6 +365,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(entry),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
+ any(UiEventLogger.class),
eq(false),
eq(false),
eq(true) /* wasShownHighPriority */);
@@ -394,6 +398,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(entry),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
+ any(UiEventLogger.class),
eq(true),
eq(false),
eq(false) /* wasShownHighPriority */);
@@ -424,6 +429,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(entry),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
+ any(UiEventLogger.class),
eq(false),
eq(false),
eq(false) /* wasShownHighPriority */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 6bf60721cd8e..ed982ab7d989 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -62,6 +62,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -102,6 +103,7 @@ public class NotificationInfoTest extends SysuiTestCase {
private Set<NotificationChannel> mDefaultNotificationChannelSet = new HashSet<>();
private StatusBarNotification mSbn;
private NotificationEntry mEntry;
+ private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake();
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
@@ -187,6 +189,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -211,6 +214,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -231,6 +235,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -260,6 +265,7 @@ public class NotificationInfoTest extends SysuiTestCase {
entry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -281,6 +287,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -307,6 +314,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -328,6 +336,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -348,6 +357,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -372,6 +382,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -392,6 +403,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
true,
true);
@@ -416,6 +428,7 @@ public class NotificationInfoTest extends SysuiTestCase {
latch.countDown();
},
null,
+ mUiEventLogger,
true,
false,
true);
@@ -439,6 +452,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -462,6 +476,7 @@ public class NotificationInfoTest extends SysuiTestCase {
assertEquals(mNotificationChannel, c);
},
null,
+ mUiEventLogger,
false,
false,
true);
@@ -482,6 +497,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -496,6 +512,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
(View v, NotificationChannel c, int appUid) -> { },
null,
+ mUiEventLogger,
true,
false,
true);
@@ -519,6 +536,7 @@ public class NotificationInfoTest extends SysuiTestCase {
latch.countDown();
},
null,
+ mUiEventLogger,
true,
true,
true);
@@ -543,6 +561,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -565,6 +584,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -587,6 +607,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
true,
true);
@@ -611,6 +632,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -630,6 +652,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -649,6 +672,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -658,6 +682,28 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@Test
+ public void testBindNotification_LogsOpen() throws Exception {
+ mNotificationInfo.bindNotification(
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ mChannelEditorDialogController,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mNotificationChannelSet,
+ mEntry,
+ null,
+ null,
+ mUiEventLogger,
+ true,
+ false,
+ true);
+ assertEquals(1, mUiEventLogger.numLogs());
+ assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(),
+ mUiEventLogger.eventId(0));
+ }
+
+ @Test
public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(
@@ -671,6 +717,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -696,6 +743,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -721,6 +769,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -730,6 +779,13 @@ public class NotificationInfoTest extends SysuiTestCase {
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
assertEquals(originalImportance, mNotificationChannel.getImportance());
+
+ assertEquals(2, mUiEventLogger.numLogs());
+ assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(),
+ mUiEventLogger.eventId(0));
+ // The SAVE_IMPORTANCE event is logged whenever importance is saved, even if unchanged.
+ assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_SAVE_IMPORTANCE.getId(),
+ mUiEventLogger.eventId(1));
}
@Test
@@ -747,6 +803,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -773,6 +830,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -789,6 +847,12 @@ public class NotificationInfoTest extends SysuiTestCase {
assertTrue((updated.getValue().getUserLockedFields()
& USER_LOCKED_IMPORTANCE) != 0);
assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+
+ assertEquals(2, mUiEventLogger.numLogs());
+ assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(),
+ mUiEventLogger.eventId(0));
+ assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_SAVE_IMPORTANCE.getId(),
+ mUiEventLogger.eventId(1));
}
@Test
@@ -805,6 +869,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -838,6 +903,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -871,6 +937,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -907,6 +974,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -942,6 +1010,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
true);
@@ -968,6 +1037,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -997,6 +1067,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -1029,6 +1100,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false);
@@ -1040,6 +1112,10 @@ public class NotificationInfoTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
+
+ assertEquals(1, mUiEventLogger.numLogs());
+ assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(),
+ mUiEventLogger.eventId(0));
}
@Test
@@ -1056,6 +1132,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false
@@ -1088,6 +1165,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false
@@ -1113,6 +1191,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
+ mUiEventLogger,
true,
false,
false
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index c4bd1b281b24..b286f9486e13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -53,6 +53,7 @@ import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FeatureFlags;
@@ -133,6 +134,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Mock private MetricsLogger mMetricsLogger;
@Mock private NotificationRoundnessManager mNotificationRoundnessManager;
@Mock private KeyguardBypassController mKeyguardBypassController;
+ @Mock private KeyguardMediaController mKeyguardMediaController;
@Mock private ZenModeController mZenModeController;
@Mock private NotificationSectionsManager mNotificationSectionsManager;
@Mock private NotificationSection mNotificationSection;
@@ -209,6 +211,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mock(SysuiStatusBarStateController.class),
mHeadsUpManager,
mKeyguardBypassController,
+ mKeyguardMediaController,
new FalsingManagerFake(),
mLockscreenUserManager,
mock(NotificationGutsManager.class),
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 32e2b04e8e4f..12daa6142d5c 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -33,6 +33,7 @@ java_defaults {
"net-utils-framework-common",
],
libs: [
+ "framework-statsd.stubs.module_lib",
"framework-tethering.impl",
"framework-wifi",
"unsupportedappusage",
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index cc095a0bb4a7..4f053cb65c38 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -171,6 +171,14 @@ public class TetheringManager {
*/
public static final int TETHERING_ETHERNET = 5;
+ /**
+ * WIGIG tethering type. Use a separate type to prevent
+ * conflicts with TETHERING_WIFI
+ * This type is only used internally by the tethering module
+ * @hide
+ */
+ public static final int TETHERING_WIGIG = 6;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml
index 9269c6f0fd52..9b9dcde910e7 100644
--- a/packages/Tethering/res/values/config.xml
+++ b/packages/Tethering/res/values/config.xml
@@ -43,6 +43,13 @@
</string-array>
<!-- List of regexpressions describing the interface (if any) that represent tetherable
+ WiGig interfaces. If the device doesn't want to support tethering over WiGig this
+ should be empty. An example would be "wigig\\d" -->
+ <string-array translatable="false" name="config_tether_wigig_regexs">
+ <item>"wigig\\d"</item>
+ </string-array>
+
+ <!-- List of regexpressions describing the interface (if any) that represent tetherable
Wifi P2P interfaces. If the device doesn't want to support tethering over Wifi P2p this
should be empty. An example would be "p2p-p2p\\d-.*" -->
<string-array translatable="false" name="config_tether_wifi_p2p_regexs">
diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml
index 4e2bb1e31b2a..6a33d55cb0de 100644
--- a/packages/Tethering/res/values/overlayable.xml
+++ b/packages/Tethering/res/values/overlayable.xml
@@ -20,6 +20,7 @@
<item type="array" name="config_tether_usb_regexs"/>
<item type="array" name="config_tether_ncm_regexs" />
<item type="array" name="config_tether_wifi_regexs"/>
+ <item type="array" name="config_tether_wigig_regexs"/>
<item type="array" name="config_tether_wifi_p2p_regexs"/>
<item type="array" name="config_tether_bluetooth_regexs"/>
<item type="array" name="config_tether_dhcp_range"/>
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 35c156304c77..8af1797a9dd7 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -617,7 +617,8 @@ public class IpServer extends StateMachine {
final Boolean setIfaceUp;
if (mInterfaceType == TetheringManager.TETHERING_WIFI
|| mInterfaceType == TetheringManager.TETHERING_WIFI_P2P
- || mInterfaceType == TetheringManager.TETHERING_ETHERNET) {
+ || mInterfaceType == TetheringManager.TETHERING_ETHERNET
+ || mInterfaceType == TetheringManager.TETHERING_WIGIG) {
// 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.
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index fe92204c25c8..33b9d00e70dc 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -16,8 +16,11 @@
package com.android.networkstack.tethering;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static android.net.util.TetheringUtils.uint16;
+import android.annotation.NonNull;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
@@ -25,6 +28,7 @@ import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.net.netlink.NetlinkSocket;
+import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.net.util.SocketUtils;
import android.os.Handler;
@@ -37,9 +41,11 @@ import android.system.OsConstants;
import com.android.internal.annotations.VisibleForTesting;
import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
import java.io.IOException;
import java.net.SocketAddress;
import java.net.SocketException;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.NoSuchElementException;
@@ -63,6 +69,11 @@ public class OffloadHardwareInterface {
private static final int NF_NETLINK_CONNTRACK_NEW = 1;
private static final int NF_NETLINK_CONNTRACK_UPDATE = 2;
private static final int NF_NETLINK_CONNTRACK_DESTROY = 4;
+ // Reference libnetfilter_conntrack/linux_nfnetlink_conntrack.h
+ public static final short NFNL_SUBSYS_CTNETLINK = 1;
+ public static final short IPCTNL_MSG_CT_GET = 1;
+
+ private final long NETLINK_MESSAGE_TIMEOUT_MS = 500;
private final Handler mHandler;
private final SharedLog mLog;
@@ -226,6 +237,9 @@ public class OffloadHardwareInterface {
NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
if (h1 == null) return false;
+ sendNetlinkMessage(h1, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET),
+ (short) (NLM_F_REQUEST | NLM_F_DUMP));
+
final NativeHandle h2 = mDeps.createConntrackSocket(
NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
if (h2 == null) {
@@ -252,6 +266,25 @@ public class OffloadHardwareInterface {
return results.mSuccess;
}
+ @VisibleForTesting
+ public void sendNetlinkMessage(@NonNull NativeHandle handle, short type, short flags) {
+ final int length = StructNlMsgHdr.STRUCT_SIZE;
+ final byte[] msg = new byte[length];
+ final StructNlMsgHdr nlh = new StructNlMsgHdr();
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(msg);
+ nlh.nlmsg_len = length;
+ nlh.nlmsg_type = type;
+ nlh.nlmsg_flags = flags;
+ nlh.nlmsg_seq = 1;
+ nlh.pack(byteBuffer);
+ try {
+ NetlinkSocket.sendMessage(handle.getFileDescriptor(), msg, 0 /* offset */, length,
+ NETLINK_MESSAGE_TIMEOUT_MS);
+ } catch (ErrnoException | InterruptedIOException e) {
+ mLog.e("Unable to send netfilter message, error: " + e);
+ }
+ }
+
private void closeFdInNativeHandle(final NativeHandle h) {
try {
h.close();
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
index c72ac52740d7..3695ec65d5c0 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -40,6 +40,7 @@ import static android.net.TetheringManager.TETHERING_NCM;
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.TetheringManager.TETHERING_WIGIG;
import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
@@ -495,7 +496,8 @@ public class Tethering {
if (up) {
maybeTrackNewInterfaceLocked(iface);
} else {
- if (ifaceNameToType(iface) == TETHERING_BLUETOOTH) {
+ if (ifaceNameToType(iface) == TETHERING_BLUETOOTH
+ || ifaceNameToType(iface) == TETHERING_WIGIG) {
stopTrackingInterfaceLocked(iface);
} else {
// Ignore usb0 down after enabling RNDIS.
@@ -517,6 +519,8 @@ public class Tethering {
if (cfg.isWifi(iface)) {
return TETHERING_WIFI;
+ } else if (cfg.isWigig(iface)) {
+ return TETHERING_WIGIG;
} else if (cfg.isWifiP2p(iface)) {
return TETHERING_WIFI_P2P;
} else if (cfg.isUsb(iface)) {
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 18b2b7804fb0..e1771a561370 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -92,6 +92,7 @@ public class TetheringConfiguration {
public final String[] tetherableUsbRegexs;
public final String[] tetherableWifiRegexs;
+ public final String[] tetherableWigigRegexs;
public final String[] tetherableWifiP2pRegexs;
public final String[] tetherableBluetoothRegexs;
public final String[] tetherableNcmRegexs;
@@ -125,6 +126,7 @@ public class TetheringConfiguration {
// us an interface name. Careful consideration needs to be given to
// implications for Settings and for provisioning checks.
tetherableWifiRegexs = getResourceStringArray(res, R.array.config_tether_wifi_regexs);
+ tetherableWigigRegexs = getResourceStringArray(res, R.array.config_tether_wigig_regexs);
tetherableWifiP2pRegexs = getResourceStringArray(
res, R.array.config_tether_wifi_p2p_regexs);
tetherableBluetoothRegexs = getResourceStringArray(
@@ -167,6 +169,11 @@ public class TetheringConfiguration {
return matchesDownstreamRegexs(iface, tetherableWifiRegexs);
}
+ /** Check whether input interface belong to wigig.*/
+ public boolean isWigig(String iface) {
+ return matchesDownstreamRegexs(iface, tetherableWigigRegexs);
+ }
+
/** Check whether this interface is Wifi P2P interface. */
public boolean isWifiP2p(String iface) {
return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
index f8ff1cb29c23..c543fad62dba 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
@@ -17,13 +17,17 @@
package com.android.networkstack.tethering;
import static android.net.util.TetheringUtils.uint16;
+import static android.system.OsConstants.SOCK_STREAM;
+import static android.system.OsConstants.AF_UNIX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
@@ -31,11 +35,14 @@ import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
+import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.NativeHandle;
import android.os.test.TestLooper;
+import android.system.ErrnoException;
import android.system.OsConstants;
+import android.system.Os;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -47,6 +54,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.FileDescriptor;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
@@ -64,6 +74,10 @@ public final class OffloadHardwareInterfaceTest {
@Mock private IOffloadControl mIOffloadControl;
@Mock private NativeHandle mNativeHandle;
+ // Random values to test Netlink message.
+ private static final short TEST_TYPE = 184;
+ private static final short TEST_FLAGS = 263;
+
class MyDependencies extends OffloadHardwareInterface.Dependencies {
MyDependencies(SharedLog log) {
super(log);
@@ -203,6 +217,31 @@ public final class OffloadHardwareInterfaceTest {
eq(uint16(udpParams.dst.port)));
}
+ @Test
+ public void testNetlinkMessage() throws Exception {
+ FileDescriptor writeSocket = new FileDescriptor();
+ FileDescriptor readSocket = new FileDescriptor();
+ try {
+ Os.socketpair(AF_UNIX, SOCK_STREAM, 0, writeSocket, readSocket);
+ } catch (ErrnoException e) {
+ fail();
+ return;
+ }
+ when(mNativeHandle.getFileDescriptor()).thenReturn(writeSocket);
+
+ mOffloadHw.sendNetlinkMessage(mNativeHandle, TEST_TYPE, TEST_FLAGS);
+
+ ByteBuffer buffer = ByteBuffer.allocate(StructNlMsgHdr.STRUCT_SIZE);
+ int read = Os.read(readSocket, buffer);
+
+ buffer.flip();
+ assertEquals(StructNlMsgHdr.STRUCT_SIZE, buffer.getInt());
+ assertEquals(TEST_TYPE, buffer.getShort());
+ assertEquals(TEST_FLAGS, buffer.getShort());
+ assertEquals(1 /* seq */, buffer.getInt());
+ assertEquals(0 /* pid */, buffer.getInt());
+ }
+
private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
final NatTimeoutUpdate params = new NatTimeoutUpdate();
params.proto = proto;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 7f912a4fc1ce..d2b1bd1a6008 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -56,6 +56,8 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.fingerprint.IFingerprintService;
@@ -190,6 +192,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private final SimpleStringSplitter mStringColonSplitter =
new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
+ private final Rect mTempRect = new Rect();
+ private final Rect mTempRect1 = new Rect();
+
private final PackageManager mPackageManager;
private final PowerManager mPowerManager;
@@ -246,6 +251,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
//TODO: Remove this hack
private boolean mInitialized;
+ private Point mTempPoint;
private boolean mIsAccessibilityButtonShown;
private AccessibilityUserState getCurrentUserStateLocked() {
@@ -1068,6 +1074,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
/**
+ * Gets a point within the accessibility focused node where we can send down
+ * and up events to perform a click.
+ *
+ * @param outPoint The click point to populate.
+ * @return Whether accessibility a click point was found and set.
+ */
+ // TODO: (multi-display) Make sure this works for multiple displays.
+ public boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
+ return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
+ }
+
+ /**
* Perform an accessibility action on the view that currently has accessibility focus.
* Has no effect if no item has accessibility focus, if the item with accessibility
* focus does not expose the specified action, or if the action fails.
@@ -1081,6 +1099,32 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action);
}
+ /**
+ * Returns true if accessibility focus is confined to the active window.
+ */
+ public boolean accessibilityFocusOnlyInActiveWindow() {
+ synchronized (mLock) {
+ return mA11yWindowManager.isTrackingWindowsLocked();
+ }
+ }
+
+ /**
+ * Gets the bounds of a window.
+ *
+ * @param outBounds The output to which to write the bounds.
+ */
+ boolean getWindowBounds(int windowId, Rect outBounds) {
+ IBinder token;
+ synchronized (mLock) {
+ token = getWindowToken(windowId, mCurrentUserId);
+ }
+ mWindowManagerService.getWindowFrame(token, outBounds);
+ if (!outBounds.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
public int getActiveWindowId() {
return mA11yWindowManager.getActiveWindowId(mCurrentUserId);
}
@@ -1824,9 +1868,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
for (int i = 0; !observingWindows && (i < boundServiceCount); i++) {
AccessibilityServiceConnection boundService = boundServices.get(i);
if (boundService.canRetrieveInteractiveWindowsLocked()) {
+ userState.setAccessibilityFocusOnlyInActiveWindow(false);
observingWindows = true;
}
}
+ userState.setAccessibilityFocusOnlyInActiveWindow(true);
// Gets all valid displays and start tracking windows of each display if there is at least
// one bound service that can retrieve window content.
@@ -2930,6 +2976,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
/**
+ * Gets a point within the accessibility focused node where we can send down and up events
+ * to perform a click.
+ *
+ * @param outPoint The click point to populate.
+ * @return Whether accessibility a click point was found and set.
+ */
+ // TODO: (multi-display) Make sure this works for multiple displays.
+ boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
+ return getInteractionBridge()
+ .getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
+ }
+
+ /**
* Perform an accessibility action on the view that currently has accessibility focus.
* Has no effect if no item has accessibility focus, if the item with accessibility
* focus does not expose the specified action, or if the action fails.
@@ -2947,6 +3006,43 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return focus.performAction(action.getId());
}
+ public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
+ AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
+ if (focus == null) {
+ return false;
+ }
+
+ synchronized (mLock) {
+ Rect boundsInScreen = mTempRect;
+ focus.getBoundsInScreen(boundsInScreen);
+
+ // Apply magnification if needed.
+ MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
+ if (spec != null && !spec.isNop()) {
+ boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ boundsInScreen.scale(1 / spec.scale);
+ }
+
+ // Clip to the window bounds.
+ Rect windowBounds = mTempRect1;
+ getWindowBounds(focus.getWindowId(), windowBounds);
+ if (!boundsInScreen.intersect(windowBounds)) {
+ return false;
+ }
+
+ // Clip to the screen bounds.
+ Point screenSize = mTempPoint;
+ mDefaultDisplay.getRealSize(screenSize);
+ if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) {
+ return false;
+ }
+
+ outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
+ }
+
+ return true;
+ }
+
private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
final int focusedWindowId;
synchronized (mLock) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 43bb4b384bb2..0845d019c060 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -104,6 +104,7 @@ class AccessibilityUserState {
private boolean mIsDisplayMagnificationEnabled;
private boolean mIsFilterKeyEventsEnabled;
private boolean mIsPerformGesturesEnabled;
+ private boolean mAccessibilityFocusOnlyInActiveWindow;
private boolean mIsTextHighContrastEnabled;
private boolean mIsTouchExplorationEnabled;
private boolean mServiceHandlesDoubleTap;
@@ -685,6 +686,13 @@ class AccessibilityUserState {
mIsPerformGesturesEnabled = enabled;
}
+ public boolean isAccessibilityFocusOnlyInActiveWindow() {
+ return mAccessibilityFocusOnlyInActiveWindow;
+ }
+
+ public void setAccessibilityFocusOnlyInActiveWindow(boolean enabled) {
+ mAccessibilityFocusOnlyInActiveWindow = enabled;
+ }
public ComponentName getServiceChangingSoftKeyboardModeLocked() {
return mServiceChangingSoftKeyboardMode;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/FullScreenMagnificationGestureHandler.java
index afe6238ca38f..b7f8e674f3ba 100644
--- a/services/accessibility/java/com/android/server/accessibility/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/FullScreenMagnificationGestureHandler.java
@@ -26,6 +26,7 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils.logMagnificationTripleTap;
import static com.android.server.accessibility.gestures.GestureUtils.distance;
+import static com.android.server.accessibility.gestures.GestureUtils.distanceClosestPointerToPoint;
import static java.lang.Math.abs;
import static java.util.Arrays.asList;
@@ -37,6 +38,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.PointF;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -615,6 +617,7 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
+ private static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3;
final int mLongTapMinDelay;
final int mSwipeMinDistance;
@@ -626,6 +629,7 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
private MotionEvent mPreLastDown;
private MotionEvent mLastUp;
private MotionEvent mPreLastUp;
+ private PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN);
private long mLastDetectingDownEventTime;
@@ -656,6 +660,10 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
transitionToDelegatingStateAndClear();
}
break;
+ case MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE: {
+ transitToPanningScalingStateAndClear();
+ }
+ break;
default: {
throw new IllegalArgumentException("Unknown message type: " + type);
}
@@ -702,14 +710,20 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
}
break;
case ACTION_POINTER_DOWN: {
- if (mMagnificationController.isMagnifying(mDisplayId)) {
- transitionTo(mPanningScalingState);
- clear();
+ if (mMagnificationController.isMagnifying(mDisplayId)
+ && event.getPointerCount() == 2) {
+ storeSecondPointerDownLocation(event);
+ mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
+ ViewConfiguration.getTapTimeout());
} else {
transitionToDelegatingStateAndClear();
}
}
break;
+ case ACTION_POINTER_UP: {
+ transitionToDelegatingStateAndClear();
+ }
+ break;
case ACTION_MOVE: {
if (isFingerDown()
&& distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
@@ -719,11 +733,19 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
// For convenience, viewport dragging takes precedence
// over insta-delegating on 3tap&swipe
// (which is a rare combo to be used aside from magnification)
- if (isMultiTapTriggered(2 /* taps */)) {
+ if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
transitionToViewportDraggingStateAndClear(event);
+ } else if (isMagnifying() && event.getPointerCount() == 2) {
+ //Primary pointer is swiping, so transit to PanningScalingState
+ transitToPanningScalingStateAndClear();
} else {
transitionToDelegatingStateAndClear();
}
+ } else if (isMagnifying() && secondPointerDownValid()
+ && distanceClosestPointerToPoint(
+ mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
+ //Second pointer is swiping, so transit to PanningScalingState
+ transitToPanningScalingStateAndClear();
}
}
break;
@@ -755,6 +777,21 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
}
}
+ private void storeSecondPointerDownLocation(MotionEvent event) {
+ final int index = event.getActionIndex();
+ mSecondPointerDownLocation.set(event.getX(index), event.getY(index));
+ }
+
+ private boolean secondPointerDownValid() {
+ return !(Float.isNaN(mSecondPointerDownLocation.x) && Float.isNaN(
+ mSecondPointerDownLocation.y));
+ }
+
+ private void transitToPanningScalingStateAndClear() {
+ transitionTo(mPanningScalingState);
+ clear();
+ }
+
public boolean isMultiTapTriggered(int numTaps) {
// Shortcut acts as the 2 initial taps
@@ -822,11 +859,13 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
setShortcutTriggered(false);
removePendingDelayedMessages();
clearDelayedMotionEvents();
+ mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
}
private void removePendingDelayedMessages() {
mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+ mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE);
}
private void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent,
@@ -890,6 +929,7 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
transitionTo(mDelegatingState);
sendDelayedMotionEvents();
removePendingDelayedMessages();
+ mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
}
private void onTripleTap(MotionEvent up) {
@@ -907,6 +947,10 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
}
}
+ private boolean isMagnifying() {
+ return mMagnificationController.isMagnifying(mDisplayId);
+ }
+
void transitionToViewportDraggingStateAndClear(MotionEvent down) {
if (DEBUG_DETECTING) Slog.i(LOG_TAG, "onTripleTapAndHold()");
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
index 667364c9c901..c8cee1079e8e 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
@@ -21,8 +21,11 @@ import static com.android.server.accessibility.gestures.TouchState.ALL_POINTER_I
import static com.android.server.accessibility.gestures.TouchState.MAX_POINTER_COUNT;
import android.content.Context;
+import android.graphics.Point;
import android.util.Slog;
import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -37,19 +40,27 @@ import com.android.server.policy.WindowManagerPolicy;
*/
class EventDispatcher {
private static final String LOG_TAG = "EventDispatcher";
+ private static final int CLICK_LOCATION_NONE = 0;
+ private static final int CLICK_LOCATION_ACCESSIBILITY_FOCUS = 1;
+ private static final int CLICK_LOCATION_LAST_TOUCH_EXPLORED = 2;
private final AccessibilityManagerService mAms;
private Context mContext;
// The receiver of motion events.
private EventStreamTransformation mReceiver;
- // Keep track of which pointers sent to the system are down.
- private int mInjectedPointersDown;
- // The time of the last injected down.
- private long mLastInjectedDownEventTime;
+ // The long pressing pointer id if coordinate remapping is needed for double tap and hold
+ private int mLongPressingPointerId = -1;
+
+ // The long pressing pointer X if coordinate remapping is needed for double tap and hold.
+ private int mLongPressingPointerDeltaX;
+
+ // The long pressing pointer Y if coordinate remapping is needed for double tap and hold.
+ private int mLongPressingPointerDeltaY;
+
+ // Temporary point to avoid instantiation.
+ private final Point mTempPoint = new Point();
- // The last injected hover event.
- private MotionEvent mLastInjectedHoverEvent;
private TouchState mState;
EventDispatcher(
@@ -98,8 +109,18 @@ class EventDispatcher {
if (action == MotionEvent.ACTION_DOWN) {
event.setDownTime(event.getEventTime());
} else {
- event.setDownTime(getLastInjectedDownEventTime());
+ event.setDownTime(mState.getLastInjectedDownEventTime());
+ }
+ // If the user is long pressing but the long pressing pointer
+ // was not exactly over the accessibility focused item we need
+ // to remap the location of that pointer so the user does not
+ // have to explicitly touch explore something to be able to
+ // long press it, or even worse to avoid the user long pressing
+ // on the wrong item since click and long press behave differently.
+ if (mLongPressingPointerId >= 0) {
+ event = offsetEvent(event, -mLongPressingPointerDeltaX, -mLongPressingPointerDeltaY);
}
+
if (DEBUG) {
Slog.d(
LOG_TAG,
@@ -116,7 +137,7 @@ class EventDispatcher {
} else {
Slog.e(LOG_TAG, "Error sending event: no receiver specified.");
}
- updateState(event);
+ mState.onInjectedMotionEvent(event);
if (event != prototype) {
event.recycle();
@@ -145,87 +166,15 @@ class EventDispatcher {
mState.onInjectedAccessibilityEvent(type);
}
- /**
- * Processes an injected {@link MotionEvent} event.
- *
- * @param event The event to process.
- */
- void updateState(MotionEvent event) {
- final int action = event.getActionMasked();
- final int pointerId = event.getPointerId(event.getActionIndex());
- final int pointerFlag = (1 << pointerId);
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- mInjectedPointersDown |= pointerFlag;
- mLastInjectedDownEventTime = event.getDownTime();
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- mInjectedPointersDown &= ~pointerFlag;
- if (mInjectedPointersDown == 0) {
- mLastInjectedDownEventTime = 0;
- }
- break;
- case MotionEvent.ACTION_HOVER_ENTER:
- case MotionEvent.ACTION_HOVER_MOVE:
- case MotionEvent.ACTION_HOVER_EXIT:
- if (mLastInjectedHoverEvent != null) {
- mLastInjectedHoverEvent.recycle();
- }
- mLastInjectedHoverEvent = MotionEvent.obtain(event);
- break;
- }
- if (DEBUG) {
- Slog.i(LOG_TAG, "Injected pointer:\n" + toString());
- }
- }
-
- /** Clears the internals state. */
- public void clear() {
- mInjectedPointersDown = 0;
- }
-
- /** @return The time of the last injected down event. */
- public long getLastInjectedDownEventTime() {
- return mLastInjectedDownEventTime;
- }
-
- /** @return The number of down pointers injected to the view hierarchy. */
- public int getInjectedPointerDownCount() {
- return Integer.bitCount(mInjectedPointersDown);
- }
-
- /** @return The bits of the injected pointers that are down. */
- public int getInjectedPointersDown() {
- return mInjectedPointersDown;
- }
-
- /**
- * Whether an injected pointer is down.
- *
- * @param pointerId The unique pointer id.
- * @return True if the pointer is down.
- */
- public boolean isInjectedPointerDown(int pointerId) {
- final int pointerFlag = (1 << pointerId);
- return (mInjectedPointersDown & pointerFlag) != 0;
- }
-
- /** @return The the last injected hover event. */
- public MotionEvent getLastInjectedHoverEvent() {
- return mLastInjectedHoverEvent;
- }
-
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("=========================");
builder.append("\nDown pointers #");
- builder.append(Integer.bitCount(mInjectedPointersDown));
+ builder.append(Integer.bitCount(mState.getInjectedPointersDown()));
builder.append(" [ ");
for (int i = 0; i < MAX_POINTER_COUNT; i++) {
- if ((mInjectedPointersDown & i) != 0) {
+ if (mState.isInjectedPointerDown(i)) {
builder.append(i);
builder.append(" ");
}
@@ -236,6 +185,48 @@ class EventDispatcher {
}
/**
+ * /** Offsets all pointers in the given event by adding the specified X and Y offsets.
+ *
+ * @param event The event to offset.
+ * @param offsetX The X offset.
+ * @param offsetY The Y offset.
+ * @return An event with the offset pointers or the original event if both offsets are zero.
+ */
+ private MotionEvent offsetEvent(MotionEvent event, int offsetX, int offsetY) {
+ if (offsetX == 0 && offsetY == 0) {
+ return event;
+ }
+ final int remappedIndex = event.findPointerIndex(mLongPressingPointerId);
+ final int pointerCount = event.getPointerCount();
+ PointerProperties[] props = PointerProperties.createArray(pointerCount);
+ PointerCoords[] coords = PointerCoords.createArray(pointerCount);
+ for (int i = 0; i < pointerCount; i++) {
+ event.getPointerProperties(i, props[i]);
+ event.getPointerCoords(i, coords[i]);
+ if (i == remappedIndex) {
+ coords[i].x += offsetX;
+ coords[i].y += offsetY;
+ }
+ }
+ return MotionEvent.obtain(
+ event.getDownTime(),
+ event.getEventTime(),
+ event.getAction(),
+ event.getPointerCount(),
+ props,
+ coords,
+ event.getMetaState(),
+ event.getButtonState(),
+ 1.0f,
+ 1.0f,
+ event.getDeviceId(),
+ event.getEdgeFlags(),
+ event.getSource(),
+ event.getDisplayId(),
+ event.getFlags());
+ }
+
+ /**
* Computes the action for an injected event based on a masked action and a pointer index.
*
* @param actionMasked The masked action.
@@ -247,7 +238,7 @@ class EventDispatcher {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
// Compute the action based on how many down pointers are injected.
- if (getInjectedPointerDownCount() == 0) {
+ if (mState.getInjectedPointerDownCount() == 0) {
return MotionEvent.ACTION_DOWN;
} else {
return (pointerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT)
@@ -255,7 +246,7 @@ class EventDispatcher {
}
case MotionEvent.ACTION_POINTER_UP:
// Compute the action based on how many down pointers are injected.
- if (getInjectedPointerDownCount() == 1) {
+ if (mState.getInjectedPointerDownCount() == 1) {
return MotionEvent.ACTION_UP;
} else {
return (pointerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT)
@@ -280,7 +271,7 @@ class EventDispatcher {
for (int i = 0; i < pointerCount; i++) {
final int pointerId = prototype.getPointerId(i);
// Do not send event for already delivered pointers.
- if (!isInjectedPointerDown(pointerId)) {
+ if (!mState.isInjectedPointerDown(pointerId)) {
pointerIdBits |= (1 << pointerId);
final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
sendMotionEvent(
@@ -306,7 +297,7 @@ class EventDispatcher {
for (int i = 0; i < pointerCount; i++) {
final int pointerId = prototype.getPointerId(i);
// Skip non injected down pointers.
- if (!isInjectedPointerDown(pointerId)) {
+ if (!mState.isInjectedPointerDown(pointerId)) {
continue;
}
final int action = computeInjectionAction(MotionEvent.ACTION_POINTER_UP, i);
@@ -315,4 +306,97 @@ class EventDispatcher {
pointerIdBits &= ~(1 << pointerId);
}
}
+
+ public boolean longPressWithTouchEvents(MotionEvent event, int policyFlags) {
+ final int pointerIndex = event.getActionIndex();
+ final int pointerId = event.getPointerId(pointerIndex);
+ Point clickLocation = mTempPoint;
+ final int result = computeClickLocation(clickLocation);
+ if (result == CLICK_LOCATION_NONE) {
+ return false;
+ }
+ mLongPressingPointerId = pointerId;
+ mLongPressingPointerDeltaX = (int) event.getX(pointerIndex) - clickLocation.x;
+ mLongPressingPointerDeltaY = (int) event.getY(pointerIndex) - clickLocation.y;
+ sendDownForAllNotInjectedPointers(event, policyFlags);
+ return true;
+ }
+
+ public void clickWithTouchEvents(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ final int pointerIndex = event.getActionIndex();
+ final int pointerId = event.getPointerId(pointerIndex);
+ Point clickLocation = mTempPoint;
+ final int result = computeClickLocation(clickLocation);
+ if (result == CLICK_LOCATION_NONE) {
+ Slog.e(LOG_TAG, "Unable to compute click location.");
+ // We can't send a click to no location, but the gesture was still
+ // consumed.
+ return;
+ }
+ // Do the click.
+ PointerProperties[] properties = new PointerProperties[1];
+ properties[0] = new PointerProperties();
+ event.getPointerProperties(pointerIndex, properties[0]);
+ PointerCoords[] coords = new PointerCoords[1];
+ coords[0] = new PointerCoords();
+ coords[0].x = clickLocation.x;
+ coords[0].y = clickLocation.y;
+ MotionEvent clickEvent =
+ MotionEvent.obtain(
+ event.getDownTime(),
+ event.getEventTime(),
+ MotionEvent.ACTION_DOWN,
+ 1,
+ properties,
+ coords,
+ 0,
+ 0,
+ 1.0f,
+ 1.0f,
+ event.getDeviceId(),
+ 0,
+ event.getSource(),
+ event.getDisplayId(),
+ event.getFlags());
+ final boolean targetAccessibilityFocus = (result == CLICK_LOCATION_ACCESSIBILITY_FOCUS);
+ sendActionDownAndUp(clickEvent, rawEvent, policyFlags, targetAccessibilityFocus);
+ clickEvent.recycle();
+ }
+
+ private int computeClickLocation(Point outLocation) {
+ if (mState.getLastInjectedHoverEventForClick() != null) {
+ final int lastExplorePointerIndex =
+ mState.getLastInjectedHoverEventForClick().getActionIndex();
+ outLocation.x =
+ (int) mState.getLastInjectedHoverEventForClick().getX(lastExplorePointerIndex);
+ outLocation.y =
+ (int) mState.getLastInjectedHoverEventForClick().getY(lastExplorePointerIndex);
+ if (!mAms.accessibilityFocusOnlyInActiveWindow()
+ || mState.getLastTouchedWindowId() == mAms.getActiveWindowId()) {
+ if (mAms.getAccessibilityFocusClickPointInScreen(outLocation)) {
+ return CLICK_LOCATION_ACCESSIBILITY_FOCUS;
+ } else {
+ return CLICK_LOCATION_LAST_TOUCH_EXPLORED;
+ }
+ }
+ }
+ if (mAms.getAccessibilityFocusClickPointInScreen(outLocation)) {
+ return CLICK_LOCATION_ACCESSIBILITY_FOCUS;
+ }
+ return CLICK_LOCATION_NONE;
+ }
+
+ private void sendActionDownAndUp(
+ MotionEvent prototype,
+ MotionEvent rawEvent,
+ int policyFlags,
+ boolean targetAccessibilityFocus) {
+ // Tap with the pointer that last explored.
+ final int pointerId = prototype.getPointerId(prototype.getActionIndex());
+ final int pointerIdBits = (1 << pointerId);
+ prototype.setTargetAccessibilityFocus(targetAccessibilityFocus);
+ sendMotionEvent(prototype, MotionEvent.ACTION_DOWN, rawEvent, pointerIdBits, policyFlags);
+ prototype.setTargetAccessibilityFocus(targetAccessibilityFocus);
+ sendMotionEvent(prototype, MotionEvent.ACTION_UP, rawEvent, pointerIdBits, policyFlags);
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index 6d0f069e51ac..e9c70c60a322 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -104,6 +104,7 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
mHandler = new Handler(context.getMainLooper());
mListener = listener;
mState = state;
+ mMultiFingerGesturesEnabled = false;
// Set up gestures.
// Start with double tap.
mGestures.add(new MultiTap(context, 2, GESTURE_DOUBLE_TAP, this));
@@ -247,7 +248,7 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
* and hold is dispatched via onGestureCompleted. Otherwise, this method is called when the
* user has performed a double tap and then held down the second tap.
*/
- void onDoubleTapAndHold();
+ void onDoubleTapAndHold(MotionEvent event, MotionEvent rawEvent, int policyFlags);
/**
* When FLAG_SERVICE_HANDLES_DOUBLE_TAP is enabled, this method is not called; double-tap is
@@ -256,7 +257,7 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
*
* @return true if the event is consumed, else false
*/
- boolean onDoubleTap();
+ boolean onDoubleTap(MotionEvent event, MotionEvent rawEvent, int policyFlags);
/**
* Called when the system has decided the event stream is a potential gesture.
@@ -322,7 +323,7 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
new AccessibilityGestureEvent(gestureId, event.getDisplayId());
mListener.onGestureCompleted(gestureEvent);
} else {
- mListener.onDoubleTap();
+ mListener.onDoubleTap(event, rawEvent, policyFlags);
}
clear();
break;
@@ -332,7 +333,7 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
new AccessibilityGestureEvent(gestureId, event.getDisplayId());
mListener.onGestureCompleted(gestureEvent);
} else {
- mListener.onDoubleTapAndHold();
+ mListener.onDoubleTapAndHold(event, rawEvent, policyFlags);
}
clear();
break;
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureUtils.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureUtils.java
index ac6748089314..ec3041848356 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureUtils.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureUtils.java
@@ -1,5 +1,6 @@
package com.android.server.accessibility.gestures;
+import android.graphics.PointF;
import android.util.MathUtils;
import android.view.MotionEvent;
@@ -38,6 +39,27 @@ public final class GestureUtils {
return MathUtils.dist(first.getX(), first.getY(), second.getX(), second.getY());
}
+ /**
+ * Returns the minimum distance between {@code pointerDown} and each pointer of
+ * {@link MotionEvent}.
+ *
+ * @param pointerDown The action pointer location of the {@link MotionEvent} with
+ * {@link MotionEvent#ACTION_DOWN} or {@link MotionEvent#ACTION_POINTER_DOWN}
+ * @param moveEvent The {@link MotionEvent} with {@link MotionEvent#ACTION_MOVE}
+ * @return the movement of the pointer.
+ */
+ public static double distanceClosestPointerToPoint(PointF pointerDown, MotionEvent moveEvent) {
+ float movement = Float.MAX_VALUE;
+ for (int i = 0; i < moveEvent.getPointerCount(); i++) {
+ final float moveDelta = MathUtils.dist(pointerDown.x, pointerDown.y, moveEvent.getX(i),
+ moveEvent.getY(i));
+ if (movement > moveDelta) {
+ movement = moveDelta;
+ }
+ }
+ return movement;
+ }
+
public static boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) {
final long deltaTime = secondUp.getEventTime() - firstUp.getEventTime();
return (deltaTime >= timeout);
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 4fee672a8803..373d47ed366b 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -22,7 +22,6 @@ import static com.android.server.accessibility.gestures.TouchState.ALL_POINTER_I
import android.accessibilityservice.AccessibilityGestureEvent;
import android.content.Context;
-import android.graphics.Point;
import android.graphics.Region;
import android.os.Handler;
import android.util.Slog;
@@ -86,6 +85,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
// The ID of the pointer used for dragging.
private int mDraggingPointerId;
+
// Handler for performing asynchronous operations.
private final Handler mHandler;
@@ -115,8 +115,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
// Handle to the accessibility manager service.
private final AccessibilityManagerService mAms;
- // Temporary point to avoid instantiation.
- private final Point mTempPoint = new Point();
// Context in which this explorer operates.
private final Context mContext;
@@ -277,6 +275,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
if (eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
sendsPendingA11yEventsIfNeed();
}
+ mState.onReceivedAccessibilityEvent(event);
super.onAccessibilityEvent(event);
}
@@ -309,16 +308,20 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
@Override
- public void onDoubleTapAndHold() {
+ public void onDoubleTapAndHold(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
// Try to use the standard accessibility API to long click
if (!mAms.performActionOnAccessibilityFocusedItem(
AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK)) {
Slog.e(LOG_TAG, "ACTION_LONG_CLICK failed.");
+ if (mDispatcher.longPressWithTouchEvents(event, policyFlags)) {
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ mState.startDelegating();
+ }
}
}
@Override
- public boolean onDoubleTap() {
+ public boolean onDoubleTap(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
mAms.onTouchInteractionEnd();
// Remove pending event deliveries.
mSendHoverEnterAndMoveDelayed.cancel();
@@ -334,7 +337,10 @@ public class TouchExplorer extends BaseEventStreamTransformation
// Try to use the standard accessibility API to click
if (!mAms.performActionOnAccessibilityFocusedItem(
AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK)) {
- Slog.e(LOG_TAG, "ACTION_CLICK failed.");
+ Slog.e(LOG_TAG, "ACTION_CLICK failed. Dispatching motion events to simulate click.");
+
+ mDispatcher.clickWithTouchEvents(event, rawEvent, policyFlags);
+ return true;
}
return true;
}
@@ -840,7 +846,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
* @param policyFlags The policy flags associated with the event.
*/
private void sendHoverExitAndTouchExplorationGestureEndIfNeeded(int policyFlags) {
- MotionEvent event = mDispatcher.getLastInjectedHoverEvent();
+ MotionEvent event = mState.getLastInjectedHoverEvent();
if (event != null && event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
final int pointerIdBits = event.getPointerIdBits();
if (!mSendTouchExplorationEndDelayed.isPending()) {
@@ -862,7 +868,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
* @param policyFlags The policy flags associated with the event.
*/
private void sendTouchExplorationGestureStartAndHoverEnterIfNeeded(int policyFlags) {
- MotionEvent event = mDispatcher.getLastInjectedHoverEvent();
+ MotionEvent event = mState.getLastInjectedHoverEvent();
if (event != null && event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
final int pointerIdBits = event.getPointerIdBits();
mDispatcher.sendMotionEvent(
@@ -1188,7 +1194,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
+ ", mDetermineUserIntentTimeout: " + mDetermineUserIntentTimeout
+ ", mDoubleTapSlop: " + mDoubleTapSlop
+ ", mDraggingPointerId: " + mDraggingPointerId
- + ", mTempPoint: " + mTempPoint
+ " }";
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
index d23dbbefd325..7a39bc29e8e5 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
@@ -75,6 +75,16 @@ public class TouchState {
private MotionEvent mLastReceivedEvent;
// The accompanying raw event without any transformations.
private MotionEvent mLastReceivedRawEvent;
+ // The id of the last touch explored window.
+ private int mLastTouchedWindowId;
+ // The last injected hover event.
+ private MotionEvent mLastInjectedHoverEvent;
+ // The last injected hover event used for performing clicks.
+ private MotionEvent mLastInjectedHoverEventForClick;
+ // The time of the last injected down.
+ private long mLastInjectedDownEventTime;
+ // Keep track of which pointers sent to the system are down.
+ private int mInjectedPointersDown;
public TouchState() {
mReceivedPointerTracker = new ReceivedPointerTracker();
@@ -88,7 +98,9 @@ public class TouchState {
mLastReceivedEvent.recycle();
mLastReceivedEvent = null;
}
+ mLastTouchedWindowId = -1;
mReceivedPointerTracker.clear();
+ mInjectedPointersDown = 0;
}
/**
@@ -107,6 +119,71 @@ public class TouchState {
mReceivedPointerTracker.onMotionEvent(rawEvent);
}
+ /**
+ * Processes an injected {@link MotionEvent} event.
+ *
+ * @param event The event to process.
+ */
+ void onInjectedMotionEvent(MotionEvent event) {
+ final int action = event.getActionMasked();
+ final int pointerId = event.getPointerId(event.getActionIndex());
+ final int pointerFlag = (1 << pointerId);
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_POINTER_DOWN:
+ mInjectedPointersDown |= pointerFlag;
+ mLastInjectedDownEventTime = event.getDownTime();
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ mInjectedPointersDown &= ~pointerFlag;
+ if (mInjectedPointersDown == 0) {
+ mLastInjectedDownEventTime = 0;
+ }
+ break;
+ case MotionEvent.ACTION_HOVER_ENTER:
+ case MotionEvent.ACTION_HOVER_MOVE:
+ if (mLastInjectedHoverEvent != null) {
+ mLastInjectedHoverEvent.recycle();
+ }
+ mLastInjectedHoverEvent = MotionEvent.obtain(event);
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ if (mLastInjectedHoverEvent != null) {
+ mLastInjectedHoverEvent.recycle();
+ }
+ mLastInjectedHoverEvent = MotionEvent.obtain(event);
+ if (mLastInjectedHoverEventForClick != null) {
+ mLastInjectedHoverEventForClick.recycle();
+ }
+ mLastInjectedHoverEventForClick = MotionEvent.obtain(event);
+ break;
+ }
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Injected pointer:\n" + toString());
+ }
+ }
+
+ /** Updates state in response to an accessibility event received from the outside. */
+ public void onReceivedAccessibilityEvent(AccessibilityEvent event) {
+ // If a new window opens or the accessibility focus moves we no longer
+ // want to click/long press on the last touch explored location.
+ switch (event.getEventType()) {
+ case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
+ case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
+ if (mLastInjectedHoverEventForClick != null) {
+ mLastInjectedHoverEventForClick.recycle();
+ mLastInjectedHoverEventForClick = null;
+ }
+ mLastTouchedWindowId = -1;
+ break;
+ case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
+ case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
+ mLastTouchedWindowId = event.getWindowId();
+ break;
+ }
+ }
+
public void onInjectedAccessibilityEvent(int type) {
// The below state transitions go here because the related events are often sent on a
// delay.
@@ -236,6 +313,46 @@ public class TouchState {
return mLastReceivedEvent;
}
+ /** @return The the last injected hover event. */
+ public MotionEvent getLastInjectedHoverEvent() {
+ return mLastInjectedHoverEvent;
+ }
+
+ /** @return The time of the last injected down event. */
+ public long getLastInjectedDownEventTime() {
+ return mLastInjectedDownEventTime;
+ }
+
+ public int getLastTouchedWindowId() {
+ return mLastTouchedWindowId;
+ }
+
+ /** @return The number of down pointers injected to the view hierarchy. */
+ public int getInjectedPointerDownCount() {
+ return Integer.bitCount(mInjectedPointersDown);
+ }
+
+ /** @return The bits of the injected pointers that are down. */
+ public int getInjectedPointersDown() {
+ return mInjectedPointersDown;
+ }
+
+ /**
+ * Whether an injected pointer is down.
+ *
+ * @param pointerId The unique pointer id.
+ * @return True if the pointer is down.
+ */
+ public boolean isInjectedPointerDown(int pointerId) {
+ final int pointerFlag = (1 << pointerId);
+ return (mInjectedPointersDown & pointerFlag) != 0;
+ }
+
+ /** @return The the last injected hover event used for a click. */
+ public MotionEvent getLastInjectedHoverEventForClick() {
+ return mLastInjectedHoverEventForClick;
+ }
+
/** This class tracks where and when a pointer went down. It does not track its movement. */
class ReceivedPointerTracker {
private static final String LOG_TAG_RECEIVED_POINTER_TRACKER = "ReceivedPointerTracker";
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 11f901538868..533bbe68e274 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -149,7 +149,7 @@ final class RemoteAugmentedAutofillService
@Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
@Nullable Function<InlineFillUi, Boolean> inlineSuggestionsCallback,
@NonNull Runnable onErrorCallback,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService, int userId) {
long requestTime = SystemClock.elapsedRealtime();
AtomicReference<ICancellationSignal> cancellationRef = new AtomicReference<>();
@@ -173,7 +173,7 @@ final class RemoteAugmentedAutofillService
inlineSuggestionsRequest, inlineSuggestionsData,
clientState, focusedId, focusedValue,
inlineSuggestionsCallback,
- client, onErrorCallback, remoteRenderService);
+ client, onErrorCallback, remoteRenderService, userId);
if (!showingFillWindow) {
requestAutofill.complete(null);
}
@@ -243,7 +243,8 @@ final class RemoteAugmentedAutofillService
@NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue,
@Nullable Function<InlineFillUi, Boolean> inlineSuggestionsCallback,
@NonNull IAutoFillManagerClient client, @NonNull Runnable onErrorCallback,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId) {
if (inlineSuggestionsData == null || inlineSuggestionsData.isEmpty()
|| inlineSuggestionsCallback == null || request == null
|| remoteRenderService == null) {
@@ -312,7 +313,7 @@ final class RemoteAugmentedAutofillService
Slog.w(TAG, "RemoteException starting intent sender");
}
}
- }, onErrorCallback, remoteRenderService);
+ }, onErrorCallback, remoteRenderService, userId, sessionId);
if (inlineSuggestionsCallback.apply(inlineFillUi)) {
mCallbacks.logAugmentedAutofillShown(sessionId, clientState);
diff --git a/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
index 617c111c6c38..80b8583759e7 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
@@ -88,9 +88,9 @@ public final class RemoteInlineSuggestionRenderService extends
*/
public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
@NonNull InlinePresentation presentation, int width, int height,
- @Nullable IBinder hostInputToken, int displayId) {
+ @Nullable IBinder hostInputToken, int displayId, int userId, int sessionId) {
scheduleAsyncRequest((s) -> s.renderSuggestion(callback, presentation, width, height,
- hostInputToken, displayId));
+ hostInputToken, displayId, userId, sessionId));
}
/**
@@ -100,6 +100,13 @@ public final class RemoteInlineSuggestionRenderService extends
scheduleAsyncRequest((s) -> s.getInlineSuggestionsRendererInfo(callback));
}
+ /**
+ * Destroys the remote inline suggestion views associated with the given user id and session id.
+ */
+ public void destroySuggestionViews(int userId, int sessionId) {
+ scheduleAsyncRequest((s) -> s.destroySuggestionViews(userId, sessionId));
+ }
+
@Nullable
private static ServiceInfo getServiceInfo(Context context, int userId) {
final String packageName =
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3114a6a02e31..9b3d075e3f2c 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -155,6 +155,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
*/
public final int id;
+ /** userId the session belongs to */
+ public final int userId;
+
/** uid the session is for */
public final int uid;
@@ -823,6 +826,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
id = sessionId;
mFlags = flags;
+ this.userId = userId;
this.taskId = taskId;
this.uid = uid;
mStartTime = SystemClock.elapsedRealtime();
@@ -1005,6 +1009,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|| disableDuration > 0) {
// Response is "empty" from an UI point of view, need to notify client.
notifyUnavailableToClient(sessionFinishedState, /* autofillableIds= */ null);
+ synchronized (mLock) {
+ mInlineSessionController.setInlineFillUiLocked(
+ InlineFillUi.emptyUi(mCurrentViewId));
+ }
}
if (requestLog != null) {
@@ -2979,10 +2987,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
inlineSuggestionsRequest.get(), response, focusedId, filterText,
/*uiCallback*/this, /*onErrorCallback*/ () -> {
synchronized (mLock) {
- mInlineSessionController.hideInlineSuggestionsUiLocked(
- focusedId);
+ mInlineSessionController.setInlineFillUiLocked(
+ InlineFillUi.emptyUi(focusedId));
}
- }, remoteRenderService);
+ }, remoteRenderService, userId, id);
return mInlineSessionController.setInlineFillUiLocked(inlineFillUi);
}
@@ -3166,12 +3174,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
notifyUnavailableToClient(AutofillManager.STATE_FINISHED, autofillableIds);
removeSelf();
} else {
- if (sVerbose) {
- if ((flags & FLAG_PASSWORD_INPUT_TYPE) != 0) {
+ if ((flags & FLAG_PASSWORD_INPUT_TYPE) != 0) {
+ if (sVerbose) {
Slog.v(TAG, "keeping session " + id + " when service returned null and "
+ "augmented service is disabled for password fields. "
+ "AutofillableIds: " + autofillableIds);
- } else {
+ }
+ mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId);
+ } else {
+ if (sVerbose) {
Slog.v(TAG, "keeping session " + id + " when service returned null but "
+ "it can be augmented. AutofillableIds: " + autofillableIds);
}
@@ -3197,7 +3208,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// non-null response but without datasets (for example, just SaveInfo)
@GuardedBy("mLock")
private Runnable triggerAugmentedAutofillLocked(int flags) {
- // (TODO: b/141703197) Fix later by passing info to service.
+ // TODO: (b/141703197) Fix later by passing info to service.
if ((flags & FLAG_PASSWORD_INPUT_TYPE) != 0) {
return null;
}
@@ -3242,7 +3253,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ ComponentName.flattenToShortString(mComponentName) + " not whitelisted ");
}
logAugmentedAutofillRequestLocked(mode, remoteService.getComponentName(),
- mCurrentViewId, isWhitelisted, /*isInline*/null);
+ mCurrentViewId, isWhitelisted, /* isInline= */ null);
return null;
}
@@ -3284,8 +3295,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
/*onErrorCallback=*/ () -> {
synchronized (mLock) {
cancelAugmentedAutofillLocked();
+
+ // Also cancel augmented in IME
+ mInlineSessionController.setInlineFillUiLocked(
+ InlineFillUi.emptyUi(mCurrentViewId));
}
- }, mService.getRemoteInlineSuggestionRenderServiceLocked());
+ }, mService.getRemoteInlineSuggestionRenderServiceLocked(), userId);
}
};
@@ -3785,6 +3800,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (mCurrentViewId != null) {
mInlineSessionController.destroyLocked(mCurrentViewId);
}
+ final RemoteInlineSuggestionRenderService remoteRenderService =
+ mService.getRemoteInlineSuggestionRenderServiceLocked();
+ if (remoteRenderService != null) {
+ remoteRenderService.destroySuggestionViews(userId, id);
+ }
+
mDestroyed = true;
// Log metrics
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 627c0733b078..25e9d5c90764 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
@@ -105,19 +105,20 @@ public final class InlineFillUi {
@NonNull AutofillId focusedViewId, @Nullable String filterText,
@NonNull AutoFillUI.AutoFillUiCallback uiCallback,
@NonNull Runnable onErrorCallback,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId) {
if (InlineSuggestionFactory.responseNeedAuthentication(response)) {
InlineSuggestion inlineAuthentication =
InlineSuggestionFactory.createInlineAuthentication(request, response,
- focusedViewId, uiCallback, onErrorCallback, remoteRenderService);
+ uiCallback, onErrorCallback, remoteRenderService, userId, sessionId);
return new InlineFillUi(focusedViewId, inlineAuthentication, filterText);
} else if (response.getDatasets() != null) {
SparseArray<Pair<Dataset, InlineSuggestion>> inlineSuggestions =
InlineSuggestionFactory.createAutofillInlineSuggestions(request,
response.getRequestId(),
response.getDatasets(), focusedViewId, uiCallback, onErrorCallback,
- remoteRenderService);
+ remoteRenderService, userId, sessionId);
return new InlineFillUi(focusedViewId, inlineSuggestions, filterText);
}
return new InlineFillUi(focusedViewId, new SparseArray<>(), filterText);
@@ -132,11 +133,12 @@ public final class InlineFillUi {
@NonNull AutofillId focusedViewId, @Nullable String filterText,
@NonNull InlineSuggestionUiCallback uiCallback,
@NonNull Runnable onErrorCallback,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId) {
SparseArray<Pair<Dataset, InlineSuggestion>> inlineSuggestions =
InlineSuggestionFactory.createAugmentedAutofillInlineSuggestions(request, datasets,
focusedViewId,
- uiCallback, onErrorCallback, remoteRenderService);
+ uiCallback, onErrorCallback, remoteRenderService, userId, sessionId);
return new InlineFillUi(focusedViewId, inlineSuggestions, filterText);
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index 462ffd668e2e..8fcb8aa9393c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -53,9 +53,9 @@ final class InlineSuggestionFactory {
public static InlineSuggestion createInlineAuthentication(
@NonNull InlineSuggestionsRequest request, @NonNull FillResponse response,
- @NonNull AutofillId autofillId,
@NonNull AutoFillUI.AutoFillUiCallback client, @NonNull Runnable onErrorCallback,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService, int userId,
+ int sessionId) {
final BiConsumer<Dataset, Integer> onClickFactory = (dataset, datasetIndex) -> {
client.authenticate(response.getRequestId(),
datasetIndex, response.getAuthentication(), response.getClientState(),
@@ -66,7 +66,8 @@ final class InlineSuggestionFactory {
InlinePresentation inlineAuthentication = response.getInlinePresentation();
return createInlineAuthSuggestion(
mergedInlinePresentation(request, 0, inlineAuthentication),
- remoteRenderService, onClickFactory, onErrorCallback, intentSenderConsumer,
+ remoteRenderService, userId, sessionId,
+ onClickFactory, onErrorCallback, intentSenderConsumer,
request.getHostInputToken(), request.getHostDisplayId());
}
@@ -80,7 +81,8 @@ final class InlineSuggestionFactory {
@NonNull List<Dataset> datasets,
@NonNull AutofillId autofillId,
@NonNull AutoFillUI.AutoFillUiCallback client, @NonNull Runnable onErrorCallback,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId) {
if (sDebug) Slog.d(TAG, "createInlineSuggestionsResponse called");
final Consumer<IntentSender> intentSenderConsumer = (intentSender) ->
client.startIntentSender(intentSender, new Intent());
@@ -90,7 +92,8 @@ final class InlineSuggestionFactory {
return createInlineSuggestionsInternal(/* isAugmented= */ false, request,
datasets, autofillId,
- onErrorCallback, onClickFactory, intentSenderConsumer, remoteRenderService);
+ onErrorCallback, onClickFactory, intentSenderConsumer, remoteRenderService, userId,
+ sessionId);
}
/**
@@ -104,7 +107,8 @@ final class InlineSuggestionFactory {
@NonNull AutofillId autofillId,
@NonNull InlineFillUi.InlineSuggestionUiCallback inlineSuggestionUiCallback,
@NonNull Runnable onErrorCallback,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId) {
if (sDebug) Slog.d(TAG, "createAugmentedInlineSuggestionsResponse called");
return createInlineSuggestionsInternal(/* isAugmented= */ true, request,
datasets, autofillId, onErrorCallback,
@@ -112,7 +116,7 @@ final class InlineSuggestionFactory {
inlineSuggestionUiCallback.autofill(dataset, datasetIndex),
(intentSender) ->
inlineSuggestionUiCallback.startIntentSender(intentSender, new Intent()),
- remoteRenderService);
+ remoteRenderService, userId, sessionId);
}
@Nullable
@@ -121,7 +125,8 @@ final class InlineSuggestionFactory {
@NonNull List<Dataset> datasets, @NonNull AutofillId autofillId,
@NonNull Runnable onErrorCallback, @NonNull BiConsumer<Dataset, Integer> onClickFactory,
@NonNull Consumer<IntentSender> intentSenderConsumer,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
+ @Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId) {
SparseArray<Pair<Dataset, InlineSuggestion>> response = new SparseArray<>(datasets.size());
for (int datasetIndex = 0; datasetIndex < datasets.size(); datasetIndex++) {
final Dataset dataset = datasets.get(datasetIndex);
@@ -139,7 +144,8 @@ final class InlineSuggestionFactory {
InlineSuggestion inlineSuggestion = createInlineSuggestion(isAugmented, dataset,
datasetIndex,
mergedInlinePresentation(request, datasetIndex, inlinePresentation),
- onClickFactory, remoteRenderService, onErrorCallback, intentSenderConsumer,
+ onClickFactory, remoteRenderService, userId, sessionId,
+ onErrorCallback, intentSenderConsumer,
request.getHostInputToken(), request.getHostDisplayId());
response.append(datasetIndex, Pair.create(dataset, inlineSuggestion));
}
@@ -151,6 +157,7 @@ final class InlineSuggestionFactory {
@NonNull InlinePresentation inlinePresentation,
@NonNull BiConsumer<Dataset, Integer> onClickFactory,
@NonNull RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId,
@NonNull Runnable onErrorCallback, @NonNull Consumer<IntentSender> intentSenderConsumer,
@Nullable IBinder hostInputToken,
int displayId) {
@@ -167,7 +174,8 @@ final class InlineSuggestionFactory {
final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlinePresentation,
() -> onClickFactory.accept(dataset, datasetIndex), onErrorCallback,
- intentSenderConsumer, remoteRenderService, hostInputToken, displayId));
+ intentSenderConsumer, remoteRenderService, userId, sessionId,
+ hostInputToken, displayId));
return inlineSuggestion;
}
@@ -175,6 +183,7 @@ final class InlineSuggestionFactory {
private static InlineSuggestion createInlineAuthSuggestion(
@NonNull InlinePresentation inlinePresentation,
@NonNull RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId,
@NonNull BiConsumer<Dataset, Integer> onClickFactory, @NonNull Runnable onErrorCallback,
@NonNull Consumer<IntentSender> intentSenderConsumer,
@Nullable IBinder hostInputToken, int displayId) {
@@ -187,8 +196,8 @@ final class InlineSuggestionFactory {
createInlineContentProvider(inlinePresentation,
() -> onClickFactory.accept(null,
AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED),
- onErrorCallback, intentSenderConsumer, remoteRenderService, hostInputToken,
- displayId));
+ onErrorCallback, intentSenderConsumer, remoteRenderService, userId,
+ sessionId, hostInputToken, displayId));
}
/**
@@ -216,12 +225,13 @@ final class InlineSuggestionFactory {
@NonNull Runnable onErrorCallback,
@NonNull Consumer<IntentSender> intentSenderConsumer,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId,
@Nullable IBinder hostInputToken,
int displayId) {
RemoteInlineSuggestionViewConnector
remoteInlineSuggestionViewConnector = new RemoteInlineSuggestionViewConnector(
- remoteRenderService, inlinePresentation, hostInputToken, displayId, onClickAction,
- onErrorCallback, intentSenderConsumer);
+ remoteRenderService, userId, sessionId, inlinePresentation, hostInputToken,
+ displayId, onClickAction, onErrorCallback, intentSenderConsumer);
InlineContentProviderImpl inlineContentProvider = new InlineContentProviderImpl(
remoteInlineSuggestionViewConnector, null);
return inlineContentProvider;
diff --git a/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java b/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java
index 9d23c171800d..7257255d1ee4 100644
--- a/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java
+++ b/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java
@@ -46,6 +46,8 @@ final class RemoteInlineSuggestionViewConnector {
@Nullable
private final IBinder mHostInputToken;
private final int mDisplayId;
+ private final int mUserId;
+ private final int mSessionId;
@NonNull
private final Runnable mOnAutofillCallback;
@@ -56,6 +58,7 @@ final class RemoteInlineSuggestionViewConnector {
RemoteInlineSuggestionViewConnector(
@Nullable RemoteInlineSuggestionRenderService remoteRenderService,
+ int userId, int sessionId,
@NonNull InlinePresentation inlinePresentation,
@Nullable IBinder hostInputToken,
int displayId,
@@ -66,6 +69,8 @@ final class RemoteInlineSuggestionViewConnector {
mInlinePresentation = inlinePresentation;
mHostInputToken = hostInputToken;
mDisplayId = displayId;
+ mUserId = userId;
+ mSessionId = sessionId;
mOnAutofillCallback = onAutofillCallback;
mOnErrorCallback = onErrorCallback;
@@ -82,7 +87,7 @@ final class RemoteInlineSuggestionViewConnector {
if (mRemoteRenderService != null) {
if (sDebug) Slog.d(TAG, "Request to recreate the UI");
mRemoteRenderService.renderSuggestion(callback, mInlinePresentation, width, height,
- mHostInputToken, mDisplayId);
+ mHostInputToken, mDisplayId, mUserId, mSessionId);
return true;
}
return false;
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 507e98369855..1c3116699b2d 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -33,6 +33,7 @@ import android.graphics.drawable.Drawable;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.IBinder;
+import android.os.UserHandle;
import android.service.autofill.BatchUpdates;
import android.service.autofill.CustomDescription;
import android.service.autofill.InternalOnClickAction;
@@ -196,7 +197,9 @@ final class SaveUi {
}
intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
- PendingIntent p = PendingIntent.getActivity(this, 0, intent, 0);
+ PendingIntent p = PendingIntent.getActivityAsUser(
+ this, /* requestCode= */ 0, intent, /* flags= */ 0, /* options= */ null,
+ UserHandle.CURRENT);
if (sDebug) {
Slog.d(TAG, "startActivity add save UI restored with intent=" + intent);
}
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index dc35c774f71e..f6c4918a7dfe 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -318,7 +318,7 @@ public class UserBackupManagerService {
private static final String SERIAL_ID_FILE = "serial_id";
- private static final String SKIP_USER_FACING_DATA = "backup_skip_user_facing_data";
+ private static final String SKIP_USER_FACING_PACKAGES = "backup_skip_user_facing_packages";
private static final String WALLPAPER_PACKAGE = "com.android.wallpaperbackup";
private final @UserIdInt int mUserId;
@@ -3557,7 +3557,7 @@ public class UserBackupManagerService {
}
/**
- * We want to skip backup/restore of certain packages if 'backup_skip_user_facing_data' is
+ * We want to skip backup/restore of certain packages if 'backup_skip_user_facing_packages' is
* set to true in secure settings. See b/153940088 for details.
*
* TODO(b/154822946): Remove this logic in the next release.
@@ -3581,7 +3581,7 @@ public class UserBackupManagerService {
@VisibleForTesting
public boolean shouldSkipUserFacingData() {
- return Settings.Secure.getInt(mContext.getContentResolver(), SKIP_USER_FACING_DATA,
+ return Settings.Secure.getInt(mContext.getContentResolver(), SKIP_USER_FACING_PACKAGES,
/* def */ 0) != 0;
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 6859c5835c80..d6759b3e2cca 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -336,8 +336,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
@Override
public List<String> getAssociations(String callingPackage, int userId)
throws RemoteException {
- checkCallerIsSystemOr(callingPackage, userId);
- checkUsesFeature(callingPackage, getCallingUserId());
+ if (!callerCanManageCompanionDevices()) {
+ checkCallerIsSystemOr(callingPackage, userId);
+ checkUsesFeature(callingPackage, getCallingUserId());
+ }
return new ArrayList<>(CollectionUtils.map(
readAllAssociations(userId, callingPackage),
a -> a.deviceAddress));
@@ -353,6 +355,12 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
removeAssociation(getCallingUserId(), callingPackage, deviceMacAddress);
}
+ private boolean callerCanManageCompanionDevices() {
+ return getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_COMPANION_DEVICES)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
private void checkCallerIsSystemOr(String pkg) throws RemoteException {
checkCallerIsSystemOr(pkg, getCallingUserId());
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 65e98ac8e684..4bba0d892f3b 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -95,7 +95,6 @@ java_library_static {
"android.hardware.light-V2.0-java",
"android.hardware.power-java",
"android.hardware.power-V1.0-java",
- "android.hardware.tv.cec-V1.0-java",
"android.hardware.vibrator-java",
"android.net.ipsec.ike.stubs.module_lib",
"app-compat-annotations",
@@ -117,6 +116,7 @@ java_library_static {
"android.hardware.health-V2.0-java",
"android.hardware.health-V2.1-java",
"android.hardware.light-java",
+ "android.hardware.tv.cec-V1.0-java",
"android.hardware.weaver-V1.0-java",
"android.hardware.biometrics.face-V1.0-java",
"android.hardware.biometrics.fingerprint-V2.2-java",
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 36ba610085e1..01b2e691d43a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -67,6 +67,7 @@ import android.app.BroadcastOptions;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -2487,10 +2488,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
final long DIAG_TIME_MS = 5000;
for (NetworkAgentInfo nai : networksSortedById()) {
+ PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(nai.network);
// Start gathering diagnostic information.
netDiags.add(new NetworkDiagnostics(
nai.network,
new LinkProperties(nai.linkProperties), // Must be a copy.
+ privateDnsCfg,
DIAG_TIME_MS));
}
@@ -3075,7 +3078,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Only the system server can register notifications with package "android"
final long token = Binder.clearCallingIdentity();
try {
- pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ pendingIntent = PendingIntent.getBroadcast(
+ mContext,
+ 0 /* requestCode */,
+ intent,
+ PendingIntent.FLAG_IMMUTABLE);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3931,6 +3938,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.decreaseIndent();
}
+ // TODO: This method is copied from TetheringNotificationUpdater. Should have a utility class to
+ // unify the method.
+ private static @NonNull String getSettingsPackageName(@NonNull final PackageManager pm) {
+ final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
+ final ComponentName settingsComponent = settingsIntent.resolveActivity(pm);
+ return settingsComponent != null
+ ? settingsComponent.getPackageName() : "com.android.settings";
+ }
+
private void showNetworkNotification(NetworkAgentInfo nai, NotificationType type) {
final String action;
final boolean highPriority;
@@ -3965,12 +3981,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (type != NotificationType.PRIVATE_DNS_BROKEN) {
intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setClassName("com.android.settings",
- "com.android.settings.wifi.WifiNoInternetDialog");
+ // Some OEMs have their own Settings package. Thus, need to get the current using
+ // Settings package name instead of just use default name "com.android.settings".
+ final String settingsPkgName = getSettingsPackageName(mContext.getPackageManager());
+ intent.setClassName(settingsPkgName,
+ settingsPkgName + ".wifi.WifiNoInternetDialog");
}
PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
- mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+ mContext,
+ 0 /* requestCode */,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+ null /* options */,
+ UserHandle.CURRENT);
mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, highPriority);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b46bebbd03d5..6e8eca3f46cf 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -458,6 +458,12 @@ class StorageManagerService extends IStorageManager.Stub
"(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?");
+ /** Automotive device unlockes users before system boot complete and this requires special
+ * handling as vold reset can lead into race conditions. When this is set, all users unlocked
+ * in {@code UserManager} level are unlocked after vold reset.
+ */
+ private final boolean mIsAutomotive;
+
private VolumeInfo findVolumeByIdOrThrow(String id) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(id);
@@ -1082,14 +1088,12 @@ class StorageManagerService extends IStorageManager.Stub
Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
+ ", mDaemonConnected=" + mDaemonConnected);
if (mBootCompleted && mDaemonConnected) {
- final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+ final List<UserInfo> users = userManager.getUsers();
if (mIsFuseEnabled) {
mStorageSessionController.onReset(mVold, () -> {
- mHandler.removeMessages(H_RESET);
- mHandler.removeMessages(H_VOLUME_BROADCAST);
- mHandler.removeMessages(H_VOLUME_MOUNT);
- mHandler.removeMessages(H_VOLUME_UNMOUNT);
+ mHandler.removeCallbacksAndMessages(null);
});
} else {
killMediaProvider(users);
@@ -1097,7 +1101,9 @@ class StorageManagerService extends IStorageManager.Stub
final int[] systemUnlockedUsers;
synchronized (mLock) {
- systemUnlockedUsers = mSystemUnlockedUsers;
+ // make copy as sorting can change order
+ systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers,
+ mSystemUnlockedUsers.length);
mDisks.clear();
mVolumes.clear();
@@ -1119,6 +1125,9 @@ class StorageManagerService extends IStorageManager.Stub
mVold.onUserStarted(userId);
mStoraged.onUserStarted(userId);
}
+ if (mIsAutomotive) {
+ restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
+ }
mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
mStorageManagerInternal.onReset(mVold);
} catch (Exception e) {
@@ -1127,6 +1136,29 @@ class StorageManagerService extends IStorageManager.Stub
}
}
+ private void restoreAllUnlockedUsers(UserManager userManager, List<UserInfo> allUsers,
+ int[] systemUnlockedUsers) throws Exception {
+ Arrays.sort(systemUnlockedUsers);
+ UserManager.invalidateIsUserUnlockedCache();
+ for (UserInfo user : allUsers) {
+ int userId = user.id;
+ if (!userManager.isUserRunning(userId)) {
+ continue;
+ }
+ if (Arrays.binarySearch(systemUnlockedUsers, userId) >= 0) {
+ continue;
+ }
+ boolean unlockingOrUnlocked = userManager.isUserUnlockingOrUnlocked(userId);
+ if (!unlockingOrUnlocked) {
+ continue;
+ }
+ Slog.w(TAG, "UNLOCK_USER lost from vold reset, will retry, user:" + userId);
+ mVold.onUserStarted(userId);
+ mStoraged.onUserStarted(userId);
+ mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
+ }
+ }
+
private void onUnlockUser(int userId) {
Slog.d(TAG, "onUnlockUser " + userId);
@@ -1157,6 +1189,15 @@ class StorageManagerService extends IStorageManager.Stub
// Record user as started so newly mounted volumes kick off events
// correctly, then synthesize events for any already-mounted volumes.
synchronized (mLock) {
+ if (mIsAutomotive) {
+ for (int unlockedUser : mSystemUnlockedUsers) {
+ if (unlockedUser == userId) {
+ // This can happen as restoreAllUnlockedUsers can double post the message.
+ Log.i(TAG, "completeUnlockUser called for already unlocked user:" + userId);
+ return;
+ }
+ }
+ }
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
@@ -1822,6 +1863,9 @@ class StorageManagerService extends IStorageManager.Stub
if (WATCHDOG_ENABLE) {
Watchdog.getInstance().addMonitor(this);
}
+
+ mIsAutomotive = context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE);
}
/**
@@ -4477,6 +4521,7 @@ class StorageManagerService extends IStorageManager.Stub
pw.println("Forced scoped storage app list: "
+ DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
PROP_FORCED_SCOPED_STORAGE_WHITELIST));
+ pw.println("isAutomotive:" + mIsAutomotive);
}
synchronized (mObbMounts) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a7bf98280af8..56953708e383 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -622,7 +622,7 @@ public final class ActiveServices {
}
mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null,
- true, false, null);
+ true, false, null, false);
}
final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -1464,7 +1464,7 @@ public final class ActiveServices {
mAm.mAppOpsService.startOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
- null, true, false, "");
+ null, true, false, "", false);
FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
r.appInfo.uid, r.shortInstanceName,
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 4ff421e6cdf5..135ac9a7846e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -87,6 +87,7 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_PROCESS_START_ASYNC = "process_start_async";
static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
+ static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold";
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -119,6 +120,7 @@ final class ActivityManagerConstants extends ContentObserver {
private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
+ private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000;
// Flag stored in the DeviceConfig API.
/**
@@ -328,6 +330,12 @@ final class ActivityManagerConstants extends ContentObserver {
*/
public ArraySet<Integer> IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES = new ArraySet<Integer>();
+ /**
+ * The threshold for the amount of PendingIntent for each UID, there will be
+ * warning logs if the number goes beyond this threshold.
+ */
+ public int PENDINGINTENT_WARNING_THRESHOLD = DEFAULT_PENDINGINTENT_WARNING_THRESHOLD;
+
private List<String> mDefaultImperceptibleKillExemptPackages;
private List<Integer> mDefaultImperceptibleKillExemptProcStates;
@@ -562,6 +570,8 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_MEMORY_INFO_THROTTLE_TIME);
TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
DEFAULT_TOP_TO_FGS_GRACE_DURATION);
+ PENDINGINTENT_WARNING_THRESHOLD = mParser.getInt(KEY_PENDINGINTENT_WARNING_THRESHOLD,
+ DEFAULT_PENDINGINTENT_WARNING_THRESHOLD);
// For new flags that are intended for server-side experiments, please use the new
// DeviceConfig package.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3e6a17325f5c..a5d99e019f98 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -82,8 +82,6 @@ import static android.os.Process.removeAllProcessGroups;
import static android.os.Process.sendSignal;
import static android.os.Process.setThreadPriority;
import static android.os.Process.setThreadScheduler;
-import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
-import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
@@ -335,7 +333,7 @@ import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.TriFunction;
import com.android.server.AlarmManagerInternal;
@@ -405,9 +403,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -2545,7 +2541,8 @@ public class ActivityManagerService extends IActivityManager.Stub
mUiHandler = injector.getUiHandler(null /* service */);
mUserController = hasHandlerThread ? new UserController(this) : null;
mPendingIntentController = hasHandlerThread
- ? new PendingIntentController(handlerThread.getLooper(), mUserController) : null;
+ ? new PendingIntentController(handlerThread.getLooper(), mUserController,
+ mConstants) : null;
mProcStartHandlerThread = null;
mProcStartHandler = null;
mHiddenApiBlacklist = null;
@@ -2642,7 +2639,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mUserController = new UserController(this);
mPendingIntentController = new PendingIntentController(
- mHandlerThread.getLooper(), mUserController);
+ mHandlerThread.getLooper(), mUserController, mConstants);
if (SystemProperties.getInt("sys.use_fifo_ui", 0) != 0) {
mUseFifoUiScheduling = true;
@@ -3272,7 +3269,7 @@ public class ActivityManagerService extends IActivityManager.Stub
private boolean hasUsageStatsPermission(String callingPackage) {
final int mode = mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS,
- Binder.getCallingUid(), callingPackage, null, false, "");
+ Binder.getCallingUid(), callingPackage, null, false, "", false);
if (mode == AppOpsManager.MODE_DEFAULT) {
return checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
== PackageManager.PERMISSION_GRANTED;
@@ -6100,7 +6097,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO moltmann: Allow to specify featureId
return mActivityManagerService.mAppOpsService
.noteOperation(AppOpsManager.strOpToOp(op), uid, packageName, null,
- false, "");
+ false, "", false);
}
@Override
@@ -9203,16 +9200,31 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
final long identity = Binder.clearCallingIdentity();
try {
- boolean permissionChange = KILL_APP_REASON_PERMISSIONS_REVOKED.equals(reason)
- || KILL_APP_REASON_GIDS_CHANGED.equals(reason);
mProcessList.killPackageProcessesLocked(null /* packageName */, appId, userId,
ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
true /* callerWillRestart */, true /* doit */, true /* evenPersistent */,
false /* setRemoved */,
- permissionChange ? ApplicationExitInfo.REASON_PERMISSION_CHANGE
- : ApplicationExitInfo.REASON_OTHER,
- permissionChange ? ApplicationExitInfo.SUBREASON_UNKNOWN
- : ApplicationExitInfo.SUBREASON_KILL_UID,
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_UID,
+ reason != null ? reason : "kill uid");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void killUidForPermissionChange(int appId, int userId, String reason) {
+ enforceCallingPermission(Manifest.permission.KILL_UID, "killUid");
+ synchronized (this) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mProcessList.killPackageProcessesLocked(null /* packageName */, appId, userId,
+ ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
+ true /* callerWillRestart */, true /* doit */, true /* evenPersistent */,
+ false /* setRemoved */,
+ ApplicationExitInfo.REASON_PERMISSION_CHANGE,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
reason != null ? reason : "kill uid");
} finally {
Binder.restoreCallingIdentity(identity);
@@ -20143,8 +20155,8 @@ public class ActivityManagerService extends IActivityManager.Stub
private final int mTargetUid;
private @Nullable String[] mPermissions;
- ShellDelegate(String targetPacakgeName, int targetUid, @Nullable String[] permissions) {
- mTargetPackageName = targetPacakgeName;
+ ShellDelegate(String targetPackageName, int targetUid, @Nullable String[] permissions) {
+ mTargetPackageName = targetPackageName;
mTargetUid = targetUid;
mPermissions = permissions;
}
@@ -20191,20 +20203,20 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public int noteOperation(int code, int uid, @Nullable String packageName,
@Nullable String featureId, boolean shouldCollectAsyncNotedOp,
- @Nullable String message,
- @NonNull HexFunction<Integer, Integer, String, String, Boolean, String, Integer>
- superImpl) {
+ @Nullable String message, boolean shouldCollectMessage,
+ @NonNull HeptFunction<Integer, Integer, String, String, Boolean, String, Boolean,
+ Integer> superImpl) {
if (uid == mTargetUid && isTargetOp(code)) {
final long identity = Binder.clearCallingIdentity();
try {
return superImpl.apply(code, Process.SHELL_UID, "com.android.shell", featureId,
- shouldCollectAsyncNotedOp, message);
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
return superImpl.apply(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
- message);
+ message, shouldCollectMessage);
}
@Override
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index eacf08889b1d..c62df56a88c5 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -41,8 +41,12 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.RingBuffer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AlarmManagerInternal;
import com.android.server.LocalServices;
@@ -52,6 +56,7 @@ import com.android.server.wm.SafeActivityOptions;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
@@ -66,6 +71,9 @@ public class PendingIntentController {
private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentController" : TAG_AM;
private static final String TAG_MU = TAG + POSTFIX_MU;
+ /** @see {@link #mRecentIntentsPerUid}. */
+ private static final int RECENT_N = 10;
+
/** Lock for internal state. */
final Object mLock = new Object();
final Handler mH;
@@ -77,10 +85,22 @@ public class PendingIntentController {
final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
= new HashMap<>();
- PendingIntentController(Looper looper, UserController userController) {
+ /** The number of PendingIntentRecord per uid */
+ @GuardedBy("mLock")
+ private final SparseIntArray mIntentsPerUid = new SparseIntArray();
+
+ /** The recent PendingIntentRecord, up to {@link #RECENT_N} per uid */
+ @GuardedBy("mLock")
+ private final SparseArray<RingBuffer<String>> mRecentIntentsPerUid = new SparseArray<>();
+
+ private final ActivityManagerConstants mConstants;
+
+ PendingIntentController(Looper looper, UserController userController,
+ ActivityManagerConstants constants) {
mH = new Handler(looper);
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mUserController = userController;
+ mConstants = constants;
}
void onActivityManagerInternalAdded() {
@@ -136,12 +156,14 @@ public class PendingIntentController {
}
makeIntentSenderCanceled(rec);
mIntentSenderRecords.remove(key);
+ decrementUidStatLocked(rec);
}
if (noCreate) {
return rec;
}
rec = new PendingIntentRecord(this, key, callingUid);
mIntentSenderRecords.put(key, rec.ref);
+ incrementUidStatLocked(rec);
return rec;
}
}
@@ -198,6 +220,7 @@ public class PendingIntentController {
didSomething = true;
it.remove();
makeIntentSenderCanceled(pir);
+ decrementUidStatLocked(pir);
if (pir.key.activity != null) {
final Message m = PooledLambda.obtainMessage(
PendingIntentController::clearPendingResultForActivity, this,
@@ -237,6 +260,7 @@ public class PendingIntentController {
synchronized (mLock) {
makeIntentSenderCanceled(rec);
mIntentSenderRecords.remove(rec.key);
+ decrementUidStatLocked(rec);
if (cleanActivity && rec.key.activity != null) {
final Message m = PooledLambda.obtainMessage(
PendingIntentController::clearPendingResultForActivity, this,
@@ -369,9 +393,81 @@ public class PendingIntentController {
}
}
+ final int sizeOfIntentsPerUid = mIntentsPerUid.size();
+ if (sizeOfIntentsPerUid > 0) {
+ for (int i = 0; i < sizeOfIntentsPerUid; i++) {
+ pw.print(" * UID: ");
+ pw.print(mIntentsPerUid.keyAt(i));
+ pw.print(" total: ");
+ pw.println(mIntentsPerUid.valueAt(i));
+ }
+ }
+
if (!printed) {
pw.println(" (nothing)");
}
}
}
+
+ /**
+ * Increment the number of the PendingIntentRecord for the given uid, log a warning
+ * if there are too many for this uid already.
+ */
+ @GuardedBy("mLock")
+ void incrementUidStatLocked(final PendingIntentRecord pir) {
+ final int uid = pir.uid;
+ final int idx = mIntentsPerUid.indexOfKey(uid);
+ int newCount = 1;
+ if (idx >= 0) {
+ newCount = mIntentsPerUid.valueAt(idx) + 1;
+ mIntentsPerUid.setValueAt(idx, newCount);
+ } else {
+ mIntentsPerUid.put(uid, newCount);
+ }
+
+ // If the number is within the range [threshold - N + 1, threshold], log it into buffer
+ final int lowBound = mConstants.PENDINGINTENT_WARNING_THRESHOLD - RECENT_N + 1;
+ RingBuffer<String> recentHistory = null;
+ if (newCount == lowBound) {
+ recentHistory = new RingBuffer(String.class, RECENT_N);
+ mRecentIntentsPerUid.put(uid, recentHistory);
+ } else if (newCount > lowBound && newCount <= mConstants.PENDINGINTENT_WARNING_THRESHOLD) {
+ recentHistory = mRecentIntentsPerUid.get(uid);
+ }
+ if (recentHistory == null) {
+ return;
+ }
+
+ recentHistory.append(pir.key.toString());
+
+ // Output the log if we are hitting the threshold
+ if (newCount == mConstants.PENDINGINTENT_WARNING_THRESHOLD) {
+ Slog.wtf(TAG, "Too many PendingIntent created for uid " + uid
+ + ", recent " + RECENT_N + ": " + Arrays.toString(recentHistory.toArray()));
+ // Clear the buffer, as we don't want to spam the log when the numbers
+ // are jumping up and down around the threshold.
+ mRecentIntentsPerUid.remove(uid);
+ }
+ }
+
+ /**
+ * Decrement the number of the PendingIntentRecord for the given uid.
+ */
+ @GuardedBy("mLock")
+ void decrementUidStatLocked(final PendingIntentRecord pir) {
+ final int uid = pir.uid;
+ final int idx = mIntentsPerUid.indexOfKey(uid);
+ if (idx >= 0) {
+ final int newCount = mIntentsPerUid.valueAt(idx) - 1;
+ // If we are going below the low threshold, no need to keep logs.
+ if (newCount == mConstants.PENDINGINTENT_WARNING_THRESHOLD - RECENT_N) {
+ mRecentIntentsPerUid.delete(uid);
+ }
+ if (newCount == 0) {
+ mIntentsPerUid.removeAt(idx);
+ } else {
+ mIntentsPerUid.setValueAt(idx, newCount);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index d54d2d7d2056..1997dbd6fc37 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -187,7 +187,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
+ " intent="
+ (requestIntent != null
? requestIntent.toShortString(false, true, false, false) : "<null>")
- + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
+ + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}"
+ + " requestCode=" + requestCode;
}
String typeName() {
@@ -499,6 +500,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
WeakReference<PendingIntentRecord> current = controller.mIntentSenderRecords.get(key);
if (current == ref) {
controller.mIntentSenderRecords.remove(key);
+ controller.decrementUidStatLocked(this);
}
}
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f2c4e4428af2..2d8d2c32a4c3 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -348,6 +348,17 @@ class UserController implements Handler.Callback {
@GuardedBy("mUserIdToUserJourneyMap")
private final SparseArray<UserJourneySession> mUserIdToUserJourneyMap = new SparseArray<>();
+ /**
+ * Sets on {@link #setInitialConfig(boolean, int, boolean)}, which is called by
+ * {@code ActivityManager} when the system is started.
+ *
+ * <p>It's useful to ignore external operations (i.e., originated outside {@code system_server},
+ * like from {@code adb shell am switch-user})) that could happen before such call is made and
+ * the system is ready.
+ */
+ @GuardedBy("mLock")
+ private boolean mInitialized;
+
UserController(ActivityManagerService service) {
this(new Injector(service));
}
@@ -372,6 +383,7 @@ class UserController implements Handler.Callback {
mUserSwitchUiEnabled = userSwitchUiEnabled;
mMaxRunningUsers = maxRunningUsers;
mDelayUserDataLocking = delayUserDataLocking;
+ mInitialized = true;
}
}
@@ -1587,6 +1599,11 @@ class UserController implements Handler.Callback {
}
boolean userSwitchUiEnabled;
synchronized (mLock) {
+ if (!mInitialized) {
+ Slog.e(TAG, "Cannot switch to User #" + targetUserId
+ + ": UserController not ready yet");
+ return false;
+ }
mTargetUserId = targetUserId;
userSwitchUiEnabled = mUserSwitchUiEnabled;
}
@@ -2422,6 +2439,7 @@ class UserController implements Handler.Callback {
pw.println(" mDelayUserDataLocking:" + mDelayUserDataLocking);
pw.println(" mMaxRunningUsers:" + mMaxRunningUsers);
pw.println(" mUserSwitchUiEnabled:" + mUserSwitchUiEnabled);
+ pw.println(" mInitialized:" + mInitialized);
}
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 73c98da6aa56..b5c173c91a53 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1724,12 +1724,12 @@ public class AppOpsService extends IAppOpsService.Stub {
return Zygote.MOUNT_EXTERNAL_NONE;
}
if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
- packageName, null, true, "External storage policy")
+ packageName, null, true, "External storage policy", true)
!= AppOpsManager.MODE_ALLOWED) {
return Zygote.MOUNT_EXTERNAL_NONE;
}
if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
- packageName, null, true, "External storage policy")
+ packageName, null, true, "External storage policy", true)
!= AppOpsManager.MODE_ALLOWED) {
return Zygote.MOUNT_EXTERNAL_READ;
}
@@ -2955,7 +2955,8 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
String proxiedAttributionTag, int proxyUid, String proxyPackageName,
- String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message) {
+ String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
+ boolean shouldCollectMessage) {
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
@@ -2972,7 +2973,7 @@ public class AppOpsService extends IAppOpsService.Stub {
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags,
- !isProxyTrusted, "proxy " + message);
+ !isProxyTrusted, "proxy " + message, shouldCollectMessage);
if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
return proxyMode;
}
@@ -2985,27 +2986,28 @@ public class AppOpsService extends IAppOpsService.Stub {
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
proxiedAttributionTag, proxyUid, resolveProxyPackageName, proxyAttributionTag,
- proxiedFlags, shouldCollectAsyncNotedOp, message);
+ proxiedFlags, shouldCollectAsyncNotedOp, message, shouldCollectMessage);
}
@Override
public int noteOperation(int code, int uid, String packageName, String attributionTag,
- boolean shouldCollectAsyncNotedOp, String message) {
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage) {
final CheckOpsDelegate delegate;
synchronized (this) {
delegate = mCheckOpsDelegate;
}
if (delegate == null) {
return noteOperationImpl(code, uid, packageName, attributionTag,
- shouldCollectAsyncNotedOp, message);
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage);
}
return delegate.noteOperation(code, uid, packageName, attributionTag,
- shouldCollectAsyncNotedOp, message, AppOpsService.this::noteOperationImpl);
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ AppOpsService.this::noteOperationImpl);
}
private int noteOperationImpl(int code, int uid, @Nullable String packageName,
@Nullable String attributionTag, boolean shouldCollectAsyncNotedOp,
- @Nullable String message) {
+ @Nullable String message, boolean shouldCollectMessage) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -3014,13 +3016,14 @@ public class AppOpsService extends IAppOpsService.Stub {
}
return noteOperationUnchecked(code, uid, resolvedPackageName, attributionTag,
Process.INVALID_UID, null, null, AppOpsManager.OP_FLAG_SELF,
- shouldCollectAsyncNotedOp, message);
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage);
}
private int noteOperationUnchecked(int code, int uid, @NonNull String packageName,
@Nullable String attributionTag, int proxyUid, String proxyPackageName,
@Nullable String proxyAttributionTag, @OpFlags int flags,
- boolean shouldCollectAsyncNotedOp, @Nullable String message) {
+ boolean shouldCollectAsyncNotedOp, @Nullable String message,
+ boolean shouldCollectMessage) {
RestrictionBypass bypass;
try {
bypass = verifyAndGetBypass(uid, packageName, attributionTag);
@@ -3090,7 +3093,8 @@ public class AppOpsService extends IAppOpsService.Stub {
flags);
if (shouldCollectAsyncNotedOp) {
- collectAsyncNotedOp(uid, packageName, code, attributionTag, message);
+ collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message,
+ shouldCollectMessage);
}
return AppOpsManager.MODE_ALLOWED;
@@ -3247,7 +3251,8 @@ public class AppOpsService extends IAppOpsService.Stub {
* @param message The message for the op noting
*/
private void collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode,
- @Nullable String attributionTag, @NonNull String message) {
+ @Nullable String attributionTag, @OpFlags int flags, @NonNull String message,
+ boolean shouldCollectMessage) {
Objects.requireNonNull(message);
int callingUid = Binder.getCallingUid();
@@ -3262,8 +3267,11 @@ public class AppOpsService extends IAppOpsService.Stub {
attributionTag, message, System.currentTimeMillis());
final boolean[] wasNoteForwarded = {false};
- reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode, attributionTag,
- message);
+ if ((flags & (OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED)) != 0
+ && shouldCollectMessage) {
+ reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode,
+ attributionTag, message);
+ }
if (callbacks != null) {
callbacks.broadcast((cb) -> {
@@ -3376,7 +3384,7 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int startOperation(IBinder clientId, int code, int uid, String packageName,
String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
- String message) {
+ String message, boolean shouldCollectMessage) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -3447,7 +3455,8 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (shouldCollectAsyncNotedOp) {
- collectAsyncNotedOp(uid, packageName, code, attributionTag, message);
+ collectAsyncNotedOp(uid, packageName, code, attributionTag, AppOpsManager.OP_FLAG_SELF,
+ message, shouldCollectMessage);
}
return AppOpsManager.MODE_ALLOWED;
@@ -3735,7 +3744,7 @@ public class AppOpsService extends IAppOpsService.Stub {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChangedForAllPkgsInUid,
this, code, uidState.uid, true, null));
- } else {
+ } else if (uidState.pkgOps != null) {
final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
if (callbacks != null) {
for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
@@ -4910,7 +4919,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (shell.packageName != null) {
shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid,
shell.packageName, shell.attributionTag, true, true,
- "appops start shell command");
+ "appops start shell command", true);
} else {
return -1;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 36272278e0e4..f8ab6f4a8b54 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -413,6 +413,13 @@ public class AudioService extends IAudioService.Stub
AppOpsManager.OP_AUDIO_MEDIA_VOLUME // STREAM_ASSISTANT
};
+ private static Set<Integer> sDeviceVolumeBehaviorSupportedDeviceOutSet = new HashSet<>(
+ Arrays.asList(
+ AudioSystem.DEVICE_OUT_HDMI,
+ AudioSystem.DEVICE_OUT_HDMI_ARC,
+ AudioSystem.DEVICE_OUT_SPDIF,
+ AudioSystem.DEVICE_OUT_LINE));
+
private final boolean mUseFixedVolume;
/**
@@ -525,7 +532,6 @@ public class AudioService extends IAudioService.Stub
// Devices for which the volume is fixed (volume is either max or muted)
Set<Integer> mFixedVolumeDevices = new HashSet<>(Arrays.asList(
- AudioSystem.DEVICE_OUT_HDMI,
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
AudioSystem.DEVICE_OUT_HDMI_ARC,
@@ -920,6 +926,8 @@ public class AudioService extends IAudioService.Stub
if (mHdmiManager != null) {
mHdmiManager.addHdmiControlStatusChangeListener(
mHdmiControlStatusChangeListenerCallback);
+ mHdmiManager.addHdmiCecVolumeControlFeatureListener(mContext.getMainExecutor(),
+ mMyHdmiCecVolumeControlFeatureListener);
}
mHdmiTvClient = mHdmiManager.getTvClient();
if (mHdmiTvClient != null) {
@@ -927,11 +935,6 @@ public class AudioService extends IAudioService.Stub
AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET);
}
mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
- if (mHdmiPlaybackClient != null) {
- // not a television: HDMI output will be always at max
- mFixedVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
- mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
- }
mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
}
}
@@ -2248,6 +2251,7 @@ public class AudioService extends IAudioService.Stub
if (mHdmiManager != null) {
// mHdmiCecSink true => mHdmiPlaybackClient != null
if (mHdmiCecSink
+ && mHdmiCecVolumeControlEnabled
&& streamTypeAlias == AudioSystem.STREAM_MUSIC
// vol change on a full volume device
&& isFullVolumeDevice(device)) {
@@ -2320,7 +2324,8 @@ public class AudioService extends IAudioService.Stub
@GuardedBy("mHdmiClientLock")
private void maybeSendSystemAudioStatusCommand(boolean isMuteAdjust) {
if (mHdmiAudioSystemClient == null
- || !mHdmiSystemAudioSupported) {
+ || !mHdmiSystemAudioSupported
+ || !mHdmiCecVolumeControlEnabled) {
return;
}
@@ -2340,7 +2345,8 @@ public class AudioService extends IAudioService.Stub
|| mHdmiTvClient == null
|| oldVolume == newVolume
|| (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
- || !mHdmiSystemAudioSupported) {
+ || !mHdmiSystemAudioSupported
+ || !mHdmiCecVolumeControlEnabled) {
return;
}
final long token = Binder.clearCallingIdentity();
@@ -2940,16 +2946,18 @@ public class AudioService extends IAudioService.Stub
mVolumeController.postVolumeChanged(streamType, flags);
}
- // If Hdmi-CEC system audio mode is on and we are a TV panel, never show volume bar.
+ // Don't show volume UI when:
+ // - Hdmi-CEC system audio mode is on and we are a TV panel
+ // - CEC volume control enabled on a set-top box
private int updateFlagsForTvPlatform(int flags) {
synchronized (mHdmiClientLock) {
- if (mHdmiTvClient != null && mHdmiSystemAudioSupported) {
+ if ((mHdmiTvClient != null && mHdmiSystemAudioSupported && mHdmiCecVolumeControlEnabled)
+ || (mHdmiPlaybackClient != null && mHdmiCecVolumeControlEnabled)) {
flags &= ~AudioManager.FLAG_SHOW_UI;
}
}
return flags;
}
-
// UI update and Broadcast Intent
private void sendMasterMuteUpdate(boolean muted, int flags) {
mVolumeController.postMasterMuteChanged(updateFlagsForTvPlatform(flags));
@@ -4042,6 +4050,11 @@ public class AudioService extends IAudioService.Stub
}
readVolumeGroupsSettings();
+
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Restoring device volume behavior");
+ }
+ restoreDeviceVolumeBehavior();
}
/** @see AudioManager#setSpeakerphoneOn(boolean) */
@@ -4901,50 +4914,47 @@ public class AudioService extends IAudioService.Stub
if (pkgName == null) {
pkgName = "";
}
- // translate Java device type to native device type (for the devices masks for full / fixed)
- final int type;
- switch (device.getType()) {
- case AudioDeviceInfo.TYPE_HDMI:
- type = AudioSystem.DEVICE_OUT_HDMI;
- break;
- case AudioDeviceInfo.TYPE_HDMI_ARC:
- type = AudioSystem.DEVICE_OUT_HDMI_ARC;
- break;
- case AudioDeviceInfo.TYPE_LINE_DIGITAL:
- type = AudioSystem.DEVICE_OUT_SPDIF;
- break;
- case AudioDeviceInfo.TYPE_AUX_LINE:
- type = AudioSystem.DEVICE_OUT_LINE;
- break;
- default:
- // unsupported for now
- throw new IllegalArgumentException("Unsupported device type " + device.getType());
+
+ int audioSystemDeviceOut = AudioDeviceInfo.convertDeviceTypeToInternalDevice(
+ device.getType());
+ setDeviceVolumeBehaviorInternal(audioSystemDeviceOut, deviceVolumeBehavior, pkgName);
+
+ persistDeviceVolumeBehavior(audioSystemDeviceOut, deviceVolumeBehavior);
+ }
+
+ private void setDeviceVolumeBehaviorInternal(int audioSystemDeviceOut,
+ @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior, @NonNull String caller) {
+ if (!sDeviceVolumeBehaviorSupportedDeviceOutSet.contains(audioSystemDeviceOut)) {
+ // unsupported for now
+ throw new IllegalArgumentException("Unsupported device type " + audioSystemDeviceOut);
}
+
// update device masks based on volume behavior
switch (deviceVolumeBehavior) {
case AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE:
- mFullVolumeDevices.remove(type);
- mFixedVolumeDevices.remove(type);
+ removeAudioSystemDeviceOutFromFullVolumeDevices(audioSystemDeviceOut);
+ removeAudioSystemDeviceOutFromFixedVolumeDevices(audioSystemDeviceOut);
break;
case AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED:
- mFullVolumeDevices.remove(type);
- mFixedVolumeDevices.add(type);
+ removeAudioSystemDeviceOutFromFullVolumeDevices(audioSystemDeviceOut);
+ addAudioSystemDeviceOutToFixedVolumeDevices(audioSystemDeviceOut);
break;
case AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL:
- mFullVolumeDevices.add(type);
- mFixedVolumeDevices.remove(type);
+ addAudioSystemDeviceOutToFullVolumeDevices(audioSystemDeviceOut);
+ removeAudioSystemDeviceOutFromFixedVolumeDevices(audioSystemDeviceOut);
break;
case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
throw new IllegalArgumentException("Absolute volume unsupported for now");
}
+
// log event and caller
sDeviceLogger.log(new AudioEventLogger.StringEvent(
- "Volume behavior " + deviceVolumeBehavior
- + " for dev=0x" + Integer.toHexString(type) + " by pkg:" + pkgName));
+ "Volume behavior " + deviceVolumeBehavior + " for dev=0x"
+ + Integer.toHexString(audioSystemDeviceOut) + " from:" + caller));
// make sure we have a volume entry for this device, and that volume is updated according
// to volume behavior
- checkAddAllFixedVolumeDevices(type, "setDeviceVolumeBehavior:" + pkgName);
+ checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
}
/**
@@ -4952,45 +4962,38 @@ public class AudioService extends IAudioService.Stub
* @param device the audio output device type
* @return the volume behavior for the device
*/
- public @AudioManager.DeviceVolumeBehavior int getDeviceVolumeBehavior(
+ public @AudioManager.DeviceVolumeBehaviorState int getDeviceVolumeBehavior(
@NonNull AudioDeviceAttributes device) {
// verify permissions
enforceModifyAudioRoutingPermission();
+
// translate Java device type to native device type (for the devices masks for full / fixed)
- final int type;
- switch (device.getType()) {
- case AudioDeviceInfo.TYPE_HEARING_AID:
- type = AudioSystem.DEVICE_OUT_HEARING_AID;
- break;
- case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
- type = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
- break;
- case AudioDeviceInfo.TYPE_HDMI:
- type = AudioSystem.DEVICE_OUT_HDMI;
- break;
- case AudioDeviceInfo.TYPE_HDMI_ARC:
- type = AudioSystem.DEVICE_OUT_HDMI_ARC;
- break;
- case AudioDeviceInfo.TYPE_LINE_DIGITAL:
- type = AudioSystem.DEVICE_OUT_SPDIF;
- break;
- case AudioDeviceInfo.TYPE_AUX_LINE:
- type = AudioSystem.DEVICE_OUT_LINE;
- break;
- default:
- // unsupported for now
- throw new IllegalArgumentException("Unsupported device type " + device.getType());
+ final int audioSystemDeviceOut = AudioDeviceInfo.convertDeviceTypeToInternalDevice(
+ device.getType());
+ if (!sDeviceVolumeBehaviorSupportedDeviceOutSet.contains(audioSystemDeviceOut)
+ && audioSystemDeviceOut != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP
+ && audioSystemDeviceOut != AudioSystem.DEVICE_OUT_HEARING_AID) {
+ throw new IllegalArgumentException("Unsupported volume behavior "
+ + audioSystemDeviceOut);
+ }
+
+ int setDeviceVolumeBehavior = retrieveStoredDeviceVolumeBehavior(audioSystemDeviceOut);
+ if (setDeviceVolumeBehavior != AudioManager.DEVICE_VOLUME_BEHAVIOR_UNSET) {
+ return setDeviceVolumeBehavior;
}
- if ((mFullVolumeDevices.contains(type))) {
+
+ // setDeviceVolumeBehavior has not been explicitly called for the device type. Deduce the
+ // current volume behavior.
+ if ((mFullVolumeDevices.contains(audioSystemDeviceOut))) {
return AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL;
}
- if ((mFixedVolumeDevices.contains(type))) {
+ if ((mFixedVolumeDevices.contains(audioSystemDeviceOut))) {
return AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED;
}
- if ((mAbsVolumeMultiModeCaseDevices.contains(type))) {
+ if ((mAbsVolumeMultiModeCaseDevices.contains(audioSystemDeviceOut))) {
return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE;
}
- if (type == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP
+ if (audioSystemDeviceOut == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP
&& mDeviceBroker.isAvrcpAbsoluteVolumeSupported()) {
return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE;
}
@@ -7113,18 +7116,20 @@ public class AudioService extends IAudioService.Stub
@GuardedBy("mHdmiClientLock")
private void updateHdmiCecSinkLocked(boolean hdmiCecSink) {
mHdmiCecSink = hdmiCecSink;
- if (mHdmiCecSink) {
- if (DEBUG_VOL) {
- Log.d(TAG, "CEC sink: setting HDMI as full vol device");
- }
- mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
- } else {
- if (DEBUG_VOL) {
- Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
+ if (!hasDeviceVolumeBehavior(AudioSystem.DEVICE_OUT_HDMI)) {
+ if (mHdmiCecSink) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "CEC sink: setting HDMI as full vol device");
+ }
+ addAudioSystemDeviceOutToFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI);
+ } else {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
+ }
+ // Android TV devices without CEC service apply software volume on
+ // HDMI output
+ removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI);
}
- // Android TV devices without CEC service apply software volume on
- // HDMI output
- mFullVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
}
checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
@@ -7141,9 +7146,21 @@ public class AudioService extends IAudioService.Stub
}
};
+ private class MyHdmiCecVolumeControlFeatureListener
+ implements HdmiControlManager.HdmiCecVolumeControlFeatureListener {
+ public void onHdmiCecVolumeControlFeature(boolean enabled) {
+ synchronized (mHdmiClientLock) {
+ if (mHdmiManager == null) return;
+ mHdmiCecVolumeControlEnabled = enabled;
+ }
+ }
+ };
+
private final Object mHdmiClientLock = new Object();
// If HDMI-CEC system audio is supported
+ // Note that for CEC volume commands mHdmiCecVolumeControlEnabled will play a role on volume
+ // commands
private boolean mHdmiSystemAudioSupported = false;
// Set only when device is tv.
@GuardedBy("mHdmiClientLock")
@@ -7161,10 +7178,16 @@ public class AudioService extends IAudioService.Stub
// Set only when device is an audio system.
@GuardedBy("mHdmiClientLock")
private HdmiAudioSystemClient mHdmiAudioSystemClient;
+ // True when volume control over HDMI CEC is used when CEC is enabled (meaningless otherwise)
+ @GuardedBy("mHdmiClientLock")
+ private boolean mHdmiCecVolumeControlEnabled;
private MyHdmiControlStatusChangeListenerCallback mHdmiControlStatusChangeListenerCallback =
new MyHdmiControlStatusChangeListenerCallback();
+ private MyHdmiCecVolumeControlFeatureListener mMyHdmiCecVolumeControlFeatureListener =
+ new MyHdmiCecVolumeControlFeatureListener();
+
@Override
public int setHdmiSystemAudioSupported(boolean on) {
int device = AudioSystem.DEVICE_NONE;
@@ -7403,6 +7426,7 @@ public class AudioService extends IAudioService.Stub
pw.print(" mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
pw.print(" mHdmiTvClient="); pw.println(mHdmiTvClient);
pw.print(" mHdmiSystemAudioSupported="); pw.println(mHdmiSystemAudioSupported);
+ pw.print(" mHdmiCecVolumeControlEnabled="); pw.println(mHdmiCecVolumeControlEnabled);
pw.print(" mIsCallScreeningModeSupported="); pw.println(mIsCallScreeningModeSupported);
pw.print(" mic mute FromSwitch=" + mMicMuteFromSwitch
+ " FromRestrictions=" + mMicMuteFromRestrictions
@@ -8944,4 +8968,91 @@ public class AudioService extends IAudioService.Stub
}
return mFullVolumeDevices.contains(deviceType);
}
+
+ //====================
+ // Helper functions for {set,get}DeviceVolumeBehavior
+ //====================
+ private static String getSettingsNameForDeviceVolumeBehavior(int deviceType) {
+ return "AudioService_DeviceVolumeBehavior_" + AudioSystem.getOutputDeviceName(deviceType);
+ }
+
+ private void persistDeviceVolumeBehavior(int deviceType,
+ @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Persisting Volume Behavior for DeviceType: " + deviceType);
+ }
+ System.putIntForUser(mContentResolver,
+ getSettingsNameForDeviceVolumeBehavior(deviceType),
+ deviceVolumeBehavior,
+ UserHandle.USER_CURRENT);
+ }
+
+ @AudioManager.DeviceVolumeBehaviorState
+ private int retrieveStoredDeviceVolumeBehavior(int deviceType) {
+ return System.getIntForUser(mContentResolver,
+ getSettingsNameForDeviceVolumeBehavior(deviceType),
+ AudioManager.DEVICE_VOLUME_BEHAVIOR_UNSET,
+ UserHandle.USER_CURRENT);
+ }
+
+ private void restoreDeviceVolumeBehavior() {
+ for (int deviceType : sDeviceVolumeBehaviorSupportedDeviceOutSet) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Retrieving Volume Behavior for DeviceType: " + deviceType);
+ }
+ int deviceVolumeBehavior = retrieveStoredDeviceVolumeBehavior(deviceType);
+ if (deviceVolumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_UNSET) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Skipping Setting Volume Behavior for DeviceType: " + deviceType);
+ }
+ continue;
+ }
+
+ setDeviceVolumeBehaviorInternal(deviceType, deviceVolumeBehavior,
+ "AudioService.restoreDeviceVolumeBehavior()");
+ }
+ }
+
+ /**
+ * @param audioSystemDeviceOut one of AudioSystem.DEVICE_OUT_*
+ * @return whether {@code audioSystemDeviceOut} has previously been set to a specific volume
+ * behavior
+ */
+ private boolean hasDeviceVolumeBehavior(
+ int audioSystemDeviceOut) {
+ return retrieveStoredDeviceVolumeBehavior(audioSystemDeviceOut)
+ != AudioManager.DEVICE_VOLUME_BEHAVIOR_UNSET;
+ }
+
+ private void addAudioSystemDeviceOutToFixedVolumeDevices(int audioSystemDeviceOut) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Adding DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
+ + " to mFixedVolumeDevices");
+ }
+ mFixedVolumeDevices.add(audioSystemDeviceOut);
+ }
+
+ private void removeAudioSystemDeviceOutFromFixedVolumeDevices(int audioSystemDeviceOut) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Removing DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
+ + " from mFixedVolumeDevices");
+ }
+ mFixedVolumeDevices.remove(audioSystemDeviceOut);
+ }
+
+ private void addAudioSystemDeviceOutToFullVolumeDevices(int audioSystemDeviceOut) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Adding DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
+ + " to mFullVolumeDevices");
+ }
+ mFullVolumeDevices.add(audioSystemDeviceOut);
+ }
+
+ private void removeAudioSystemDeviceOutFromFullVolumeDevices(int audioSystemDeviceOut) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Removing DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
+ + " from mFullVolumeDevices");
+ }
+ mFullVolumeDevices.remove(audioSystemDeviceOut);
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 506c8e39194b..cf6a7f6e8d70 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -57,6 +57,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@@ -64,7 +65,9 @@ import java.util.stream.Collectors;
* Encapsulate the management of DNS settings for networks.
*
* This class it NOT designed for concurrent access. Furthermore, all non-static
- * methods MUST be called from ConnectivityService's thread.
+ * methods MUST be called from ConnectivityService's thread. However, an exceptional
+ * case is getPrivateDnsConfig(Network) which is exclusively for
+ * ConnectivityService#dumpNetworkDiagnostics() on a random binder thread.
*
* [ Private DNS ]
* The code handling Private DNS is spread across several components, but this
@@ -236,8 +239,8 @@ public class DnsManager {
private final ContentResolver mContentResolver;
private final IDnsResolver mDnsResolver;
private final MockableSystemProperties mSystemProperties;
- // TODO: Replace these Maps with SparseArrays.
- private final Map<Integer, PrivateDnsConfig> mPrivateDnsMap;
+ private final ConcurrentHashMap<Integer, PrivateDnsConfig> mPrivateDnsMap;
+ // TODO: Replace the Map with SparseArrays.
private final Map<Integer, PrivateDnsValidationStatuses> mPrivateDnsValidationMap;
private final Map<Integer, LinkProperties> mLinkPropertiesMap;
private final Map<Integer, int[]> mTransportsMap;
@@ -247,15 +250,13 @@ public class DnsManager {
private int mSuccessThreshold;
private int mMinSamples;
private int mMaxSamples;
- private String mPrivateDnsMode;
- private String mPrivateDnsSpecifier;
public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) {
mContext = ctx;
mContentResolver = mContext.getContentResolver();
mDnsResolver = dnsResolver;
mSystemProperties = sp;
- mPrivateDnsMap = new HashMap<>();
+ mPrivateDnsMap = new ConcurrentHashMap<>();
mPrivateDnsValidationMap = new HashMap<>();
mLinkPropertiesMap = new HashMap<>();
mTransportsMap = new HashMap<>();
@@ -275,6 +276,12 @@ public class DnsManager {
mLinkPropertiesMap.remove(network.netId);
}
+ // This is exclusively called by ConnectivityService#dumpNetworkDiagnostics() which
+ // is not on the ConnectivityService handler thread.
+ public PrivateDnsConfig getPrivateDnsConfig(@NonNull Network network) {
+ return mPrivateDnsMap.getOrDefault(network.netId, PRIVATE_DNS_OFF);
+ }
+
public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
return (cfg != null)
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index a1a8e355dcec..49c16ad96eb7 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -18,12 +18,15 @@ package com.android.server.connectivity;
import static android.system.OsConstants.*;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.TrafficStats;
+import android.net.shared.PrivateDnsConfig;
import android.net.util.NetworkConstants;
import android.os.SystemClock;
import android.system.ErrnoException;
@@ -38,6 +41,8 @@ import com.android.internal.util.TrafficStatsConstants;
import libcore.io.IoUtils;
import java.io.Closeable;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;
@@ -52,6 +57,7 @@ import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -59,6 +65,12 @@ import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIServerName;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
/**
* NetworkDiagnostics
*
@@ -100,6 +112,7 @@ public class NetworkDiagnostics {
private final Network mNetwork;
private final LinkProperties mLinkProperties;
+ private final PrivateDnsConfig mPrivateDnsCfg;
private final Integer mInterfaceIndex;
private final long mTimeoutMs;
@@ -163,12 +176,15 @@ public class NetworkDiagnostics {
private final Map<Pair<InetAddress, InetAddress>, Measurement> mExplicitSourceIcmpChecks =
new HashMap<>();
private final Map<InetAddress, Measurement> mDnsUdpChecks = new HashMap<>();
+ private final Map<InetAddress, Measurement> mDnsTlsChecks = new HashMap<>();
private final String mDescription;
- public NetworkDiagnostics(Network network, LinkProperties lp, long timeoutMs) {
+ public NetworkDiagnostics(Network network, LinkProperties lp,
+ @NonNull PrivateDnsConfig privateDnsCfg, long timeoutMs) {
mNetwork = network;
mLinkProperties = lp;
+ mPrivateDnsCfg = privateDnsCfg;
mInterfaceIndex = getInterfaceIndex(mLinkProperties.getInterfaceName());
mTimeoutMs = timeoutMs;
mStartTime = now();
@@ -199,8 +215,22 @@ public class NetworkDiagnostics {
}
}
for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
- prepareIcmpMeasurement(nameserver);
- prepareDnsMeasurement(nameserver);
+ prepareIcmpMeasurement(nameserver);
+ prepareDnsMeasurement(nameserver);
+
+ // Unlike the DnsResolver which doesn't do certificate validation in opportunistic mode,
+ // DoT probes to the DNS servers will fail if certificate validation fails.
+ prepareDnsTlsMeasurement(null /* hostname */, nameserver);
+ }
+
+ for (InetAddress tlsNameserver : mPrivateDnsCfg.ips) {
+ // Reachability check is necessary since when resolving the strict mode hostname,
+ // NetworkMonitor always queries for both A and AAAA records, even if the network
+ // is IPv4-only or IPv6-only.
+ if (mLinkProperties.isReachable(tlsNameserver)) {
+ // If there are IPs, there must have been a name that resolved to them.
+ prepareDnsTlsMeasurement(mPrivateDnsCfg.hostname, tlsNameserver);
+ }
}
mCountDownLatch = new CountDownLatch(totalMeasurementCount());
@@ -222,6 +252,15 @@ public class NetworkDiagnostics {
}
}
+ private static String socketAddressToString(@NonNull SocketAddress sockAddr) {
+ // The default toString() implementation is not the prettiest.
+ InetSocketAddress inetSockAddr = (InetSocketAddress) sockAddr;
+ InetAddress localAddr = inetSockAddr.getAddress();
+ return String.format(
+ (localAddr instanceof Inet6Address ? "[%s]:%d" : "%s:%d"),
+ localAddr.getHostAddress(), inetSockAddr.getPort());
+ }
+
private void prepareIcmpMeasurement(InetAddress target) {
if (!mIcmpChecks.containsKey(target)) {
Measurement measurement = new Measurement();
@@ -252,8 +291,19 @@ public class NetworkDiagnostics {
}
}
+ private void prepareDnsTlsMeasurement(@Nullable String hostname, @NonNull InetAddress target) {
+ // This might overwrite an existing entry in mDnsTlsChecks, because |target| can be an IP
+ // address configured by the network as well as an IP address learned by resolving the
+ // strict mode DNS hostname. If the entry is overwritten, the overwritten measurement
+ // thread will not execute.
+ Measurement measurement = new Measurement();
+ measurement.thread = new Thread(new DnsTlsCheck(hostname, target, measurement));
+ mDnsTlsChecks.put(target, measurement);
+ }
+
private int totalMeasurementCount() {
- return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size();
+ return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size()
+ + mDnsTlsChecks.size();
}
private void startMeasurements() {
@@ -266,6 +316,9 @@ public class NetworkDiagnostics {
for (Measurement measurement : mDnsUdpChecks.values()) {
measurement.thread.start();
}
+ for (Measurement measurement : mDnsTlsChecks.values()) {
+ measurement.thread.start();
+ }
}
public void waitForMeasurements() {
@@ -297,6 +350,11 @@ public class NetworkDiagnostics {
measurements.add(entry.getValue());
}
}
+ for (Map.Entry<InetAddress, Measurement> entry : mDnsTlsChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet4Address) {
+ measurements.add(entry.getValue());
+ }
+ }
// IPv6 measurements second.
for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
@@ -315,6 +373,11 @@ public class NetworkDiagnostics {
measurements.add(entry.getValue());
}
}
+ for (Map.Entry<InetAddress, Measurement> entry : mDnsTlsChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet6Address) {
+ measurements.add(entry.getValue());
+ }
+ }
return measurements;
}
@@ -387,6 +450,8 @@ public class NetworkDiagnostics {
try {
mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
} finally {
+ // TODO: The tag should remain set until all traffic is sent and received.
+ // Consider tagging the socket after the measurement thread is started.
TrafficStats.setThreadStatsTag(oldTag);
}
// Setting SNDTIMEO is purely for defensive purposes.
@@ -403,13 +468,12 @@ public class NetworkDiagnostics {
mSocketAddress = Os.getsockname(mFileDescriptor);
}
- protected String getSocketAddressString() {
- // The default toString() implementation is not the prettiest.
- InetSocketAddress inetSockAddr = (InetSocketAddress) mSocketAddress;
- InetAddress localAddr = inetSockAddr.getAddress();
- return String.format(
- (localAddr instanceof Inet6Address ? "[%s]:%d" : "%s:%d"),
- localAddr.getHostAddress(), inetSockAddr.getPort());
+ protected boolean ensureMeasurementNecessary() {
+ if (mMeasurement.finishTime == 0) return false;
+
+ // Countdown latch was not decremented when the measurement failed during setup.
+ mCountDownLatch.countDown();
+ return true;
}
@Override
@@ -448,13 +512,7 @@ public class NetworkDiagnostics {
@Override
public void run() {
- // Check if this measurement has already failed during setup.
- if (mMeasurement.finishTime > 0) {
- // If the measurement failed during construction it didn't
- // decrement the countdown latch; do so here.
- mCountDownLatch.countDown();
- return;
- }
+ if (ensureMeasurementNecessary()) return;
try {
setupSocket(SOCK_DGRAM, mProtocol, TIMEOUT_SEND, TIMEOUT_RECV, 0);
@@ -462,7 +520,7 @@ public class NetworkDiagnostics {
mMeasurement.recordFailure(e.toString());
return;
}
- mMeasurement.description += " src{" + getSocketAddressString() + "}";
+ mMeasurement.description += " src{" + socketAddressToString(mSocketAddress) + "}";
// Build a trivial ICMP packet.
final byte[] icmpPacket = {
@@ -507,10 +565,10 @@ public class NetworkDiagnostics {
private static final int RR_TYPE_AAAA = 28;
private static final int PACKET_BUFSIZE = 512;
- private final Random mRandom = new Random();
+ protected final Random mRandom = new Random();
// Should be static, but the compiler mocks our puny, human attempts at reason.
- private String responseCodeStr(int rcode) {
+ protected String responseCodeStr(int rcode) {
try {
return DnsResponseCode.values()[rcode].toString();
} catch (IndexOutOfBoundsException e) {
@@ -518,7 +576,7 @@ public class NetworkDiagnostics {
}
}
- private final int mQueryType;
+ protected final int mQueryType;
public DnsUdpCheck(InetAddress target, Measurement measurement) {
super(target, measurement);
@@ -535,13 +593,7 @@ public class NetworkDiagnostics {
@Override
public void run() {
- // Check if this measurement has already failed during setup.
- if (mMeasurement.finishTime > 0) {
- // If the measurement failed during construction it didn't
- // decrement the countdown latch; do so here.
- mCountDownLatch.countDown();
- return;
- }
+ if (ensureMeasurementNecessary()) return;
try {
setupSocket(SOCK_DGRAM, IPPROTO_UDP, TIMEOUT_SEND, TIMEOUT_RECV,
@@ -550,12 +602,10 @@ public class NetworkDiagnostics {
mMeasurement.recordFailure(e.toString());
return;
}
- mMeasurement.description += " src{" + getSocketAddressString() + "}";
// This needs to be fixed length so it can be dropped into the pre-canned packet.
final String sixRandomDigits = String.valueOf(mRandom.nextInt(900000) + 100000);
- mMeasurement.description += " qtype{" + mQueryType + "}"
- + " qname{" + sixRandomDigits + "-android-ds.metric.gstatic.com}";
+ appendDnsToMeasurementDescription(sixRandomDigits, mSocketAddress);
// Build a trivial DNS packet.
final byte[] dnsPacket = getDnsQueryPacket(sixRandomDigits);
@@ -592,7 +642,7 @@ public class NetworkDiagnostics {
close();
}
- private byte[] getDnsQueryPacket(String sixRandomDigits) {
+ protected byte[] getDnsQueryPacket(String sixRandomDigits) {
byte[] rnd = sixRandomDigits.getBytes(StandardCharsets.US_ASCII);
return new byte[] {
(byte) mRandom.nextInt(), (byte) mRandom.nextInt(), // [0-1] query ID
@@ -611,5 +661,97 @@ public class NetworkDiagnostics {
0, 1 // QCLASS, set to 1 = IN (Internet)
};
}
+
+ protected void appendDnsToMeasurementDescription(
+ String sixRandomDigits, SocketAddress sockAddr) {
+ mMeasurement.description += " src{" + socketAddressToString(sockAddr) + "}"
+ + " qtype{" + mQueryType + "}"
+ + " qname{" + sixRandomDigits + "-android-ds.metric.gstatic.com}";
+ }
+ }
+
+ // TODO: Have it inherited from SimpleSocketCheck, and separate common DNS helpers out of
+ // DnsUdpCheck.
+ private class DnsTlsCheck extends DnsUdpCheck {
+ private static final int TCP_CONNECT_TIMEOUT_MS = 2500;
+ private static final int TCP_TIMEOUT_MS = 2000;
+ private static final int DNS_TLS_PORT = 853;
+ private static final int DNS_HEADER_SIZE = 12;
+
+ private final String mHostname;
+
+ public DnsTlsCheck(@Nullable String hostname, @NonNull InetAddress target,
+ @NonNull Measurement measurement) {
+ super(target, measurement);
+
+ mHostname = hostname;
+ mMeasurement.description = "DNS TLS dst{" + mTarget.getHostAddress() + "} hostname{"
+ + TextUtils.emptyIfNull(mHostname) + "}";
+ }
+
+ private SSLSocket setupSSLSocket() throws IOException {
+ // A TrustManager will be created and initialized with a KeyStore containing system
+ // CaCerts. During SSL handshake, it will be used to validate the certificates from
+ // the server.
+ SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
+ sslSocket.setSoTimeout(TCP_TIMEOUT_MS);
+
+ if (!TextUtils.isEmpty(mHostname)) {
+ // Set SNI.
+ final List<SNIServerName> names =
+ Collections.singletonList(new SNIHostName(mHostname));
+ SSLParameters params = sslSocket.getSSLParameters();
+ params.setServerNames(names);
+ sslSocket.setSSLParameters(params);
+ }
+
+ mNetwork.bindSocket(sslSocket);
+ return sslSocket;
+ }
+
+ private void sendDoTProbe(@Nullable SSLSocket sslSocket) throws IOException {
+ final String sixRandomDigits = String.valueOf(mRandom.nextInt(900000) + 100000);
+ final byte[] dnsPacket = getDnsQueryPacket(sixRandomDigits);
+
+ mMeasurement.startTime = now();
+ sslSocket.connect(new InetSocketAddress(mTarget, DNS_TLS_PORT), TCP_CONNECT_TIMEOUT_MS);
+
+ // Synchronous call waiting for the TLS handshake complete.
+ sslSocket.startHandshake();
+ appendDnsToMeasurementDescription(sixRandomDigits, sslSocket.getLocalSocketAddress());
+
+ final DataOutputStream output = new DataOutputStream(sslSocket.getOutputStream());
+ output.writeShort(dnsPacket.length);
+ output.write(dnsPacket, 0, dnsPacket.length);
+
+ final DataInputStream input = new DataInputStream(sslSocket.getInputStream());
+ final int replyLength = Short.toUnsignedInt(input.readShort());
+ final byte[] reply = new byte[replyLength];
+ int bytesRead = 0;
+ while (bytesRead < replyLength) {
+ bytesRead += input.read(reply, bytesRead, replyLength - bytesRead);
+ }
+
+ if (bytesRead > DNS_HEADER_SIZE && bytesRead == replyLength) {
+ mMeasurement.recordSuccess("1/1 " + responseCodeStr((int) (reply[3]) & 0x0f));
+ } else {
+ mMeasurement.recordFailure("1/1 Read " + bytesRead + " bytes while expected to be "
+ + replyLength + " bytes");
+ }
+ }
+
+ @Override
+ public void run() {
+ if (ensureMeasurementNecessary()) return;
+
+ // No need to restore the tag, since this thread is only used for this measurement.
+ TrafficStats.getAndSetThreadStatsTag(TrafficStatsConstants.TAG_SYSTEM_PROBE);
+
+ try (SSLSocket sslSocket = setupSSLSocket()) {
+ sendDoTProbe(sslSocket);
+ } catch (IOException e) {
+ mMeasurement.recordFailure(e.toString());
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index b84d3226362b..75ab33dbbfc7 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -17,11 +17,18 @@
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiPortInfo;
+import android.hardware.tv.cec.V1_0.CecMessage;
+import android.hardware.tv.cec.V1_0.HotplugEvent;
+import android.hardware.tv.cec.V1_0.IHdmiCec;
+import android.hardware.tv.cec.V1_0.IHdmiCec.getPhysicalAddressCallback;
+import android.hardware.tv.cec.V1_0.IHdmiCecCallback;
import android.hardware.tv.cec.V1_0.Result;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.os.Handler;
+import android.os.IHwBinder;
import android.os.Looper;
import android.os.MessageQueue;
+import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.Slog;
import android.util.SparseArray;
@@ -79,6 +86,11 @@ final class HdmiCecController {
private static final int MAX_HDMI_MESSAGE_HISTORY = 250;
+ private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
+
+ /** Cookie for matching the right end point. */
+ protected static final int HDMI_CEC_HAL_DEATH_COOKIE = 353;
+
// Predicate for whether the given logical address is remote device's one or not.
private final Predicate<Integer> mRemoteDeviceAddressPredicate = new Predicate<Integer>() {
@Override
@@ -102,10 +114,6 @@ final class HdmiCecController {
// device or issued by internal state change.
private Handler mControlHandler;
- // Stores the pointer to the native implementation of the service that
- // interacts with HAL.
- private volatile long mNativePtr;
-
private final HdmiControlService mService;
// Stores the local CEC devices in the system. Device type is used for key.
@@ -149,23 +157,21 @@ final class HdmiCecController {
* A factory method with injection of native methods for testing.
*/
static HdmiCecController createWithNativeWrapper(
- HdmiControlService service, NativeWrapper nativeWrapper) {
- HdmiCecController controller = new HdmiCecController(service, nativeWrapper);
- long nativePtr = nativeWrapper
- .nativeInit(controller, service.getServiceLooper().getQueue());
- if (nativePtr == 0L) {
- controller = null;
- return null;
- }
-
- controller.init(nativePtr);
- return controller;
+ HdmiControlService service, NativeWrapper nativeWrapper) {
+ HdmiCecController controller = new HdmiCecController(service, nativeWrapper);
+ String nativePtr = nativeWrapper.nativeInit();
+ if (nativePtr == null) {
+ HdmiLogger.warning("Couldn't get tv.cec service.");
+ return null;
+ }
+ controller.init(nativeWrapper);
+ return controller;
}
- private void init(long nativePtr) {
+ private void init(NativeWrapper nativeWrapper) {
mIoHandler = new Handler(mService.getIoLooper());
mControlHandler = new Handler(mService.getServiceLooper());
- mNativePtr = nativePtr;
+ nativeWrapper.setCallback(new HdmiCecCallback());
}
@ServiceThreadOnly
@@ -261,7 +267,7 @@ final class HdmiCecController {
HdmiPortInfo[] getPortInfos() {
- return mNativeWrapperImpl.nativeGetPortInfos(mNativePtr);
+ return mNativeWrapperImpl.nativeGetPortInfos();
}
/**
@@ -289,7 +295,7 @@ final class HdmiCecController {
int addLogicalAddress(int newLogicalAddress) {
assertRunOnServiceThread();
if (HdmiUtils.isValidAddress(newLogicalAddress)) {
- return mNativeWrapperImpl.nativeAddLogicalAddress(mNativePtr, newLogicalAddress);
+ return mNativeWrapperImpl.nativeAddLogicalAddress(newLogicalAddress);
} else {
return Result.FAILURE_INVALID_ARGS;
}
@@ -306,7 +312,7 @@ final class HdmiCecController {
for (int i = 0; i < mLocalDevices.size(); ++i) {
mLocalDevices.valueAt(i).clearAddress();
}
- mNativeWrapperImpl.nativeClearLogicalAddress(mNativePtr);
+ mNativeWrapperImpl.nativeClearLogicalAddress();
}
@ServiceThreadOnly
@@ -326,7 +332,7 @@ final class HdmiCecController {
@ServiceThreadOnly
int getPhysicalAddress() {
assertRunOnServiceThread();
- return mNativeWrapperImpl.nativeGetPhysicalAddress(mNativePtr);
+ return mNativeWrapperImpl.nativeGetPhysicalAddress();
}
/**
@@ -337,7 +343,7 @@ final class HdmiCecController {
@ServiceThreadOnly
int getVersion() {
assertRunOnServiceThread();
- return mNativeWrapperImpl.nativeGetVersion(mNativePtr);
+ return mNativeWrapperImpl.nativeGetVersion();
}
/**
@@ -348,7 +354,7 @@ final class HdmiCecController {
@ServiceThreadOnly
int getVendorId() {
assertRunOnServiceThread();
- return mNativeWrapperImpl.nativeGetVendorId(mNativePtr);
+ return mNativeWrapperImpl.nativeGetVendorId();
}
/**
@@ -361,7 +367,7 @@ final class HdmiCecController {
void setOption(int flag, boolean enabled) {
assertRunOnServiceThread();
HdmiLogger.debug("setOption: [flag:%d, enabled:%b]", flag, enabled);
- mNativeWrapperImpl.nativeSetOption(mNativePtr, flag, enabled);
+ mNativeWrapperImpl.nativeSetOption(flag, enabled);
}
/**
@@ -375,7 +381,7 @@ final class HdmiCecController {
if (!LanguageTag.isLanguage(language)) {
return;
}
- mNativeWrapperImpl.nativeSetLanguage(mNativePtr, language);
+ mNativeWrapperImpl.nativeSetLanguage(language);
}
/**
@@ -387,7 +393,7 @@ final class HdmiCecController {
@ServiceThreadOnly
void enableAudioReturnChannel(int port, boolean enabled) {
assertRunOnServiceThread();
- mNativeWrapperImpl.nativeEnableAudioReturnChannel(mNativePtr, port, enabled);
+ mNativeWrapperImpl.nativeEnableAudioReturnChannel(port, enabled);
}
/**
@@ -399,7 +405,7 @@ final class HdmiCecController {
@ServiceThreadOnly
boolean isConnected(int port) {
assertRunOnServiceThread();
- return mNativeWrapperImpl.nativeIsConnected(mNativePtr, port);
+ return mNativeWrapperImpl.nativeIsConnected(port);
}
/**
@@ -521,7 +527,7 @@ final class HdmiCecController {
// <Polling Message> is a message which has empty body.
int ret =
mNativeWrapperImpl.nativeSendCecCommand(
- mNativePtr, sourceAddress, destinationAddress, EMPTY_BODY);
+ sourceAddress, destinationAddress, EMPTY_BODY);
if (ret == SendMessageResult.SUCCESS) {
return true;
} else if (ret != SendMessageResult.NACK) {
@@ -627,7 +633,7 @@ final class HdmiCecController {
int i = 0;
int errorCode = SendMessageResult.SUCCESS;
do {
- errorCode = mNativeWrapperImpl.nativeSendCecCommand(mNativePtr,
+ errorCode = mNativeWrapperImpl.nativeSendCecCommand(
cecMessage.getSource(), cecMessage.getDestination(), body);
if (errorCode == SendMessageResult.SUCCESS) {
break;
@@ -651,7 +657,7 @@ final class HdmiCecController {
}
/**
- * Called by native when incoming CEC message arrived.
+ * Called when incoming CEC message arrived.
*/
@ServiceThreadOnly
private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
@@ -663,7 +669,7 @@ final class HdmiCecController {
}
/**
- * Called by native when a hotplug event issues.
+ * Called when a hotplug event issues.
*/
@ServiceThreadOnly
private void handleHotplug(int port, boolean connected) {
@@ -710,18 +716,19 @@ final class HdmiCecController {
}
protected interface NativeWrapper {
- long nativeInit(HdmiCecController handler, MessageQueue messageQueue);
- int nativeSendCecCommand(long controllerPtr, int srcAddress, int dstAddress, byte[] body);
- int nativeAddLogicalAddress(long controllerPtr, int logicalAddress);
- void nativeClearLogicalAddress(long controllerPtr);
- int nativeGetPhysicalAddress(long controllerPtr);
- int nativeGetVersion(long controllerPtr);
- int nativeGetVendorId(long controllerPtr);
- HdmiPortInfo[] nativeGetPortInfos(long controllerPtr);
- void nativeSetOption(long controllerPtr, int flag, boolean enabled);
- void nativeSetLanguage(long controllerPtr, String language);
- void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag);
- boolean nativeIsConnected(long controllerPtr, int port);
+ String nativeInit();
+ void setCallback(HdmiCecCallback callback);
+ int nativeSendCecCommand(int srcAddress, int dstAddress, byte[] body);
+ int nativeAddLogicalAddress(int logicalAddress);
+ void nativeClearLogicalAddress();
+ int nativeGetPhysicalAddress();
+ int nativeGetVersion();
+ int nativeGetVendorId();
+ HdmiPortInfo[] nativeGetPortInfos();
+ void nativeSetOption(int flag, boolean enabled);
+ void nativeSetLanguage(String language);
+ void nativeEnableAudioReturnChannel(int port, boolean flag);
+ boolean nativeIsConnected(int port);
}
private static native long nativeInit(HdmiCecController handler, MessageQueue messageQueue);
@@ -739,67 +746,200 @@ final class HdmiCecController {
int port, boolean flag);
private static native boolean nativeIsConnected(long controllerPtr, int port);
- private static final class NativeWrapperImpl implements NativeWrapper {
+ private static final class NativeWrapperImpl implements NativeWrapper,
+ IHwBinder.DeathRecipient, getPhysicalAddressCallback {
+ private IHdmiCec mHdmiCec;
+ private final Object mLock = new Object();
+ private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
+
+ @Override
+ public String nativeInit() {
+ return (connectToHal() ? mHdmiCec.toString() : null);
+ }
+
+ boolean connectToHal() {
+ try {
+ mHdmiCec = IHdmiCec.getService();
+ try {
+ mHdmiCec.linkToDeath(this, HDMI_CEC_HAL_DEATH_COOKIE);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Couldn't link to death : ", e);
+ }
+ } catch (RemoteException e) {
+ HdmiLogger.error("Couldn't get tv.cec service : ", e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void setCallback(HdmiCecCallback callback) {
+ try {
+ mHdmiCec.setCallback(callback);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Couldn't initialise tv.cec callback : ", e);
+ }
+ }
+
+ @Override
+ public int nativeSendCecCommand(int srcAddress, int dstAddress, byte[] body) {
+ CecMessage message = new CecMessage();
+ message.initiator = srcAddress;
+ message.destination = dstAddress;
+ message.body = new ArrayList<>(body.length);
+ for (byte b : body) {
+ message.body.add(b);
+ }
+ try {
+ return mHdmiCec.sendMessage(message);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to send CEC message : ", e);
+ return SendMessageResult.FAIL;
+ }
+ }
+
+ @Override
+ public int nativeAddLogicalAddress(int logicalAddress) {
+ try {
+ return mHdmiCec.addLogicalAddress(logicalAddress);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to add a logical address : ", e);
+ return Result.FAILURE_INVALID_ARGS;
+ }
+ }
+
+ @Override
+ public void nativeClearLogicalAddress() {
+ try {
+ mHdmiCec.clearLogicalAddress();
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to clear logical address : ", e);
+ }
+ }
@Override
- public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
- return HdmiCecController.nativeInit(handler, messageQueue);
+ public int nativeGetPhysicalAddress() {
+ try {
+ mHdmiCec.getPhysicalAddress(this);
+ return mPhysicalAddress;
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to get physical address : ", e);
+ return INVALID_PHYSICAL_ADDRESS;
+ }
}
@Override
- public int nativeSendCecCommand(long controllerPtr, int srcAddress, int dstAddress,
- byte[] body) {
- return HdmiCecController.nativeSendCecCommand(controllerPtr, srcAddress, dstAddress, body);
+ public int nativeGetVersion() {
+ try {
+ return mHdmiCec.getCecVersion();
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to get cec version : ", e);
+ return Result.FAILURE_UNKNOWN;
+ }
}
@Override
- public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
- return HdmiCecController.nativeAddLogicalAddress(controllerPtr, logicalAddress);
+ public int nativeGetVendorId() {
+ try {
+ return mHdmiCec.getVendorId();
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to get vendor id : ", e);
+ return Result.FAILURE_UNKNOWN;
+ }
}
@Override
- public void nativeClearLogicalAddress(long controllerPtr) {
- HdmiCecController.nativeClearLogicalAddress(controllerPtr);
+ public HdmiPortInfo[] nativeGetPortInfos() {
+ try {
+ ArrayList<android.hardware.tv.cec.V1_0.HdmiPortInfo> hdmiPortInfos =
+ mHdmiCec.getPortInfo();
+ HdmiPortInfo[] hdmiPortInfo = new HdmiPortInfo[hdmiPortInfos.size()];
+ int i = 0;
+ for (android.hardware.tv.cec.V1_0.HdmiPortInfo portInfo : hdmiPortInfos) {
+ hdmiPortInfo[i] = new HdmiPortInfo(portInfo.portId,
+ portInfo.type,
+ portInfo.physicalAddress,
+ portInfo.cecSupported,
+ false,
+ portInfo.arcSupported);
+ i++;
+ }
+ return hdmiPortInfo;
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to get port information : ", e);
+ return null;
+ }
}
@Override
- public int nativeGetPhysicalAddress(long controllerPtr) {
- return HdmiCecController.nativeGetPhysicalAddress(controllerPtr);
+ public void nativeSetOption(int flag, boolean enabled) {
+ try {
+ mHdmiCec.setOption(flag, enabled);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to set option : ", e);
+ }
}
@Override
- public int nativeGetVersion(long controllerPtr) {
- return HdmiCecController.nativeGetVersion(controllerPtr);
+ public void nativeSetLanguage(String language) {
+ try {
+ mHdmiCec.setLanguage(language);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to set language : ", e);
+ }
}
@Override
- public int nativeGetVendorId(long controllerPtr) {
- return HdmiCecController.nativeGetVendorId(controllerPtr);
+ public void nativeEnableAudioReturnChannel(int port, boolean flag) {
+ try {
+ mHdmiCec.enableAudioReturnChannel(port, flag);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to enable/disable ARC : ", e);
+ }
}
@Override
- public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
- return HdmiCecController.nativeGetPortInfos(controllerPtr);
+ public boolean nativeIsConnected(int port) {
+ try {
+ return mHdmiCec.isConnected(port);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Failed to get connection info : ", e);
+ return false;
+ }
}
@Override
- public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {
- HdmiCecController.nativeSetOption(controllerPtr, flag, enabled);
+ public void serviceDied(long cookie) {
+ if (cookie == HDMI_CEC_HAL_DEATH_COOKIE) {
+ HdmiLogger.error(TAG, "Service died cokkie : " + cookie + "; reconnecting");
+ connectToHal();
+ }
}
@Override
- public void nativeSetLanguage(long controllerPtr, String language) {
- HdmiCecController.nativeSetLanguage(controllerPtr, language);
+ public void onValues(int result, short addr) {
+ if (result == Result.SUCCESS) {
+ synchronized (mLock) {
+ mPhysicalAddress = new Short(addr).intValue();
+ }
+ }
}
+ }
+ final class HdmiCecCallback extends IHdmiCecCallback.Stub {
@Override
- public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {
- HdmiCecController.nativeEnableAudioReturnChannel(controllerPtr, port, flag);
+ public void onCecMessage(CecMessage message) throws RemoteException {
+ byte[] body = new byte[message.body.size()];
+ for (int i = 0; i < message.body.size(); i++) {
+ body[i] = message.body.get(i);
+ }
+ runOnServiceThread(
+ () -> handleIncomingCecCommand(message.initiator, message.destination, body));
}
@Override
- public boolean nativeIsConnected(long controllerPtr, int port) {
- return HdmiCecController.nativeIsConnected(controllerPtr, port);
+ public void onHotplugEvent(HotplugEvent event) throws RemoteException {
+ runOnServiceThread(() -> handleHotplug(event.portId, event.connected));
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 0ac4f9ee4c6d..f4a86675541d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -213,6 +213,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
mLocalDeviceAddresses = initLocalDeviceAddresses();
resetSelectRequestBuffer();
launchDeviceDiscovery();
+ startQueuedActions();
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index 2309293dcbd7..8da3c93de360 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -18,9 +18,9 @@ package com.android.server.hdmi;
import android.annotation.Nullable;
import android.os.SystemClock;
+import android.util.Log;
import android.util.Pair;
import android.util.Slog;
-import android.util.Log;
import java.util.HashMap;
@@ -71,6 +71,10 @@ final class HdmiLogger {
getLogger().errorInternal(toLogString(logMessage, objs));
}
+ static void error(String logMessage, Exception e, Object... objs) {
+ getLogger().errorInternal(toLogString(logMessage + e, objs));
+ }
+
private void errorInternal(String logMessage) {
String log = updateLog(mErrorTimingCache, logMessage);
if (!log.isEmpty()) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index de13bd86a415..70f0399d1070 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -17,6 +17,7 @@
package com.android.server.inputmethod;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.os.IBinder;
import android.view.inputmethod.InlineSuggestionsRequest;
@@ -109,6 +110,16 @@ public abstract class InputMethodManagerInternal {
int displayId);
/**
+ * Reports that IME control has transferred to the given window token, or if null that
+ * control has been taken away from client windows (and is instead controlled by the policy
+ * or SystemUI).
+ *
+ * @param windowToken the window token that is now in control, or {@code null} if no client
+ * window is in control of the IME.
+ */
+ public abstract void reportImeControl(@Nullable IBinder windowToken);
+
+ /**
* Fake implementation of {@link InputMethodManagerInternal}. All the methods do nothing.
*/
private static final InputMethodManagerInternal NOP =
@@ -151,6 +162,10 @@ public abstract class InputMethodManagerInternal {
int displayId) {
return false;
}
+
+ @Override
+ public void reportImeControl(@Nullable IBinder windowToken) {
+ }
};
/**
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index b647a1ab9873..9acb47538043 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -18,6 +18,8 @@ package com.android.server.inputmethod;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR;
+
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.Manifest;
@@ -177,6 +179,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
@@ -591,6 +594,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private boolean mCurClientInKeyguard;
/**
+ * {@code true} if the IME has not been mostly hidden via {@link android.view.InsetsController}
+ */
+ private boolean mCurPerceptible;
+
+ /**
* Set to true if our ServiceConnection is currently actively bound to
* a service (whether or not we have gotten its IBinder back yet).
*/
@@ -710,6 +718,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*/
int mImeWindowVis;
+ /**
+ * Checks if the client needs to start input.
+ */
+ private boolean mCurClientNeedStartInput = false;
+
private AlertDialog.Builder mDialogBuilder;
private AlertDialog mSwitchingDialog;
private IBinder mSwitchingDialogToken = new Binder();
@@ -2929,6 +2942,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
vis = 0;
}
+ if (!mCurPerceptible) {
+ vis = 0;
+ }
// mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked().
final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis);
if (mStatusBar != null) {
@@ -3141,6 +3157,28 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ @BinderThread
+ @Override
+ public void reportPerceptible(IBinder windowToken, boolean perceptible) {
+ Objects.requireNonNull(windowToken, "windowToken must not be null");
+ int uid = Binder.getCallingUid();
+ synchronized (mMethodMap) {
+ if (!calledFromValidUserLocked()) {
+ return;
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mCurFocusedWindow == windowToken
+ && mCurPerceptible != perceptible) {
+ mCurPerceptible = perceptible;
+ updateSystemUiLocked(mImeWindowVis, mBackDisposition);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
@GuardedBy("mMethodMap")
boolean showCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
@@ -3425,10 +3463,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
+ " attribute=" + attribute + ", token = " + windowToken);
}
- if (attribute != null) {
+ // Needs to start input when the same window focus gain but not with the same editor,
+ // or when the current client needs to start input (e.g. when focusing the same
+ // window after device turned screen on).
+ if (attribute != null && (startInputReason != WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR
+ || mCurClientNeedStartInput)) {
+ if (mIsInteractive) {
+ mCurClientNeedStartInput = false;
+ }
return startInputUncheckedLocked(cs, inputContext, missingMethods,
attribute, startInputFlags, startInputReason);
}
+
return new InputBindResult(
InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
null, null, null, -1, null);
@@ -3436,6 +3482,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurFocusedWindow = windowToken;
mCurFocusedWindowSoftInputMode = softInputMode;
mCurFocusedWindowClient = cs;
+ mCurPerceptible = true;
// Should we auto-show the IME even if the caller has not
// specified what should be done with it?
@@ -4381,6 +4428,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private void handleSetInteractive(final boolean interactive) {
synchronized (mMethodMap) {
mIsInteractive = interactive;
+ if (!interactive) {
+ mCurClientNeedStartInput = true;
+ }
updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition);
// Inform the current client of the change in active status
@@ -4992,6 +5042,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return mInputManagerInternal.transferTouchFocus(sourceInputToken, curHostInputToken);
}
+ private void reportImeControl(@Nullable IBinder windowToken) {
+ synchronized (mMethodMap) {
+ if (mCurFocusedWindow != windowToken) {
+ // mCurPerceptible was set by the focused window, but it is no longer in control,
+ // so we reset mCurPerceptible.
+ mCurPerceptible = true;
+ }
+ }
+ }
+
private static final class LocalServiceImpl extends InputMethodManagerInternal {
@NonNull
private final InputMethodManagerService mService;
@@ -5044,6 +5104,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
int displayId) {
return mService.transferTouchFocusToImeWindow(sourceInputToken, displayId);
}
+
+ @Override
+ public void reportImeControl(@Nullable IBinder windowToken) {
+ mService.reportImeControl(windowToken);
+ }
}
@BinderThread
@@ -5146,6 +5211,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
p.println(" mCurMethodId=" + mCurMethodId);
client = mCurClient;
p.println(" mCurClient=" + client + " mCurSeq=" + mCurSeq);
+ p.println(" mCurPerceptible=" + mCurPerceptible);
p.println(" mCurFocusedWindow=" + mCurFocusedWindow
+ " softInputMode=" +
InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode)
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 33c78e403ce3..2e3d3963c9df 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -221,6 +221,10 @@ public final class MultiClientInputMethodManagerService {
reportNotSupported();
return false;
}
+
+ @Override
+ public void reportImeControl(@Nullable IBinder windowToken) {
+ }
});
}
@@ -1753,6 +1757,12 @@ public final class MultiClientInputMethodManagerService {
@BinderThread
@Override
+ public void reportPerceptible(IBinder windowClient, boolean perceptible) {
+ reportNotSupported();
+ }
+
+ @BinderThread
+ @Override
public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@Nullable FileDescriptor err, String[] args, @Nullable ShellCallback callback,
ResultReceiver resultReceiver) {
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index d8acf0e331af..85544d0a1b02 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -678,8 +678,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context,
GnssLocationProvider.this::onNetworkAvailable, mLooper, mNIHandler);
- sendMessage(INITIALIZE_HANDLER, 0, null);
-
mGnssStatusListenerHelper = new GnssStatusListenerHelper(mContext, mHandler) {
@Override
protected boolean isAvailableInPlatform() {
@@ -746,6 +744,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
setProperties(PROPERTIES);
setAllowed(true);
+
+ sendMessage(INITIALIZE_HANDLER, 0, null);
}
/**
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 27216783d0d2..f882c57e49ba 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -62,6 +62,7 @@ abstract class MediaRoute2Provider {
public abstract void setRouteVolume(long requestId, String routeId, int volume);
public abstract void setSessionVolume(long requestId, String sessionId, int volume);
+ public abstract void prepareReleaseSession(@NonNull String sessionId);
@NonNull
public String getUniqueId() {
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index d6b98e2de901..85af346aa88a 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -34,11 +34,16 @@ import android.os.IBinder.DeathRecipient;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -61,6 +66,9 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
private RouteDiscoveryPreference mLastDiscoveryPreference = null;
+ @GuardedBy("mLock")
+ final List<RoutingSessionInfo> mReleasingSessions = new ArrayList<>();
+
MediaRoute2ProviderServiceProxy(@NonNull Context context, @NonNull ComponentName componentName,
int userId) {
super(componentName);
@@ -141,6 +149,19 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
}
}
+ @Override
+ public void prepareReleaseSession(@NonNull String sessionId) {
+ synchronized (mLock) {
+ for (RoutingSessionInfo session : mSessionInfos) {
+ if (TextUtils.equals(session.getId(), sessionId)) {
+ mSessionInfos.remove(session);
+ mReleasingSessions.add(session);
+ break;
+ }
+ }
+ }
+ }
+
public boolean hasComponentName(String packageName, String className) {
return mComponentName.getPackageName().equals(packageName)
&& mComponentName.getClassName().equals(className);
@@ -300,88 +321,97 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
}
private void onSessionCreated(Connection connection, long requestId,
- RoutingSessionInfo sessionInfo) {
+ RoutingSessionInfo newSession) {
if (mActiveConnection != connection) {
return;
}
- if (sessionInfo == null) {
- Slog.w(TAG, "onSessionCreated: Ignoring null sessionInfo sent from " + mComponentName);
+ if (newSession == null) {
+ Slog.w(TAG, "onSessionCreated: Ignoring null session sent from " + mComponentName);
return;
}
- sessionInfo = updateSessionInfo(sessionInfo);
+ newSession = assignProviderIdForSession(newSession);
+ String newSessionId = newSession.getId();
- boolean duplicateSessionAlreadyExists = false;
synchronized (mLock) {
- for (int i = 0; i < mSessionInfos.size(); i++) {
- if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
- duplicateSessionAlreadyExists = true;
- break;
- }
+ if (mSessionInfos.stream()
+ .anyMatch(session -> TextUtils.equals(session.getId(), newSessionId))
+ || mReleasingSessions.stream()
+ .anyMatch(session -> TextUtils.equals(session.getId(), newSessionId))) {
+ Slog.w(TAG, "onSessionCreated: Duplicate session already exists. Ignoring.");
+ return;
}
- mSessionInfos.add(sessionInfo);
+ mSessionInfos.add(newSession);
}
- if (duplicateSessionAlreadyExists) {
- Slog.w(TAG, "onSessionCreated: Duplicate session already exists. Ignoring.");
- return;
- }
-
- mCallback.onSessionCreated(this, requestId, sessionInfo);
+ mCallback.onSessionCreated(this, requestId, newSession);
}
- private void onSessionUpdated(Connection connection, RoutingSessionInfo sessionInfo) {
+ private void onSessionUpdated(Connection connection, RoutingSessionInfo updatedSession) {
if (mActiveConnection != connection) {
return;
}
- if (sessionInfo == null) {
- Slog.w(TAG, "onSessionUpdated: Ignoring null sessionInfo sent from "
+ if (updatedSession == null) {
+ Slog.w(TAG, "onSessionUpdated: Ignoring null session sent from "
+ mComponentName);
return;
}
- sessionInfo = updateSessionInfo(sessionInfo);
+ updatedSession = assignProviderIdForSession(updatedSession);
boolean found = false;
synchronized (mLock) {
for (int i = 0; i < mSessionInfos.size(); i++) {
- if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
- mSessionInfos.set(i, sessionInfo);
+ if (mSessionInfos.get(i).getId().equals(updatedSession.getId())) {
+ mSessionInfos.set(i, updatedSession);
found = true;
break;
}
}
- }
- if (!found) {
- Slog.w(TAG, "onSessionUpdated: Matching session info not found");
- return;
+ if (!found) {
+ for (RoutingSessionInfo releasingSession : mReleasingSessions) {
+ if (TextUtils.equals(releasingSession.getId(), updatedSession.getId())) {
+ return;
+ }
+ }
+ Slog.w(TAG, "onSessionUpdated: Matching session info not found");
+ return;
+ }
}
- mCallback.onSessionUpdated(this, sessionInfo);
+ mCallback.onSessionUpdated(this, updatedSession);
}
- private void onSessionReleased(Connection connection, RoutingSessionInfo sessionInfo) {
+ private void onSessionReleased(Connection connection, RoutingSessionInfo releaedSession) {
if (mActiveConnection != connection) {
return;
}
- if (sessionInfo == null) {
- Slog.w(TAG, "onSessionReleased: Ignoring null sessionInfo sent from " + mComponentName);
+ if (releaedSession == null) {
+ Slog.w(TAG, "onSessionReleased: Ignoring null session sent from " + mComponentName);
return;
}
- sessionInfo = updateSessionInfo(sessionInfo);
+ releaedSession = assignProviderIdForSession(releaedSession);
boolean found = false;
synchronized (mLock) {
- for (int i = 0; i < mSessionInfos.size(); i++) {
- if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
- mSessionInfos.remove(i);
+ for (RoutingSessionInfo session : mSessionInfos) {
+ if (TextUtils.equals(session.getId(), releaedSession.getId())) {
+ mSessionInfos.remove(session);
found = true;
break;
}
}
+ if (!found) {
+ for (RoutingSessionInfo session : mReleasingSessions) {
+ if (TextUtils.equals(session.getId(), releaedSession.getId())) {
+ mReleasingSessions.remove(session);
+ return;
+ }
+ }
+ }
}
if (!found) {
@@ -389,10 +419,10 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
return;
}
- mCallback.onSessionReleased(this, sessionInfo);
+ mCallback.onSessionReleased(this, releaedSession);
}
- private RoutingSessionInfo updateSessionInfo(RoutingSessionInfo sessionInfo) {
+ private RoutingSessionInfo assignProviderIdForSession(RoutingSessionInfo sessionInfo) {
return new RoutingSessionInfo.Builder(sessionInfo)
.setOwnerPackageName(mComponentName.getPackageName())
.setProviderId(getUniqueId())
@@ -423,6 +453,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
mCallback.onSessionReleased(this, sessionInfo);
}
mSessionInfos.clear();
+ mReleasingSessions.clear();
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 72d296fc5f6b..cc9503995ad9 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -16,9 +16,7 @@
package com.android.server.media;
-import static android.media.MediaRoute2ProviderService.REASON_ROUTE_NOT_AVAILABLE;
import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
-import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
import static android.media.MediaRouter2Utils.getOriginalId;
import static android.media.MediaRouter2Utils.getProviderId;
@@ -33,6 +31,8 @@ import android.media.IMediaRouter2;
import android.media.IMediaRouter2Manager;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
+import android.media.MediaRoute2ProviderService;
+import android.media.MediaRouter2Manager;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
import android.os.Binder;
@@ -235,30 +235,17 @@ class MediaRouter2ServiceImpl {
}
public void requestCreateSessionWithRouter2(IMediaRouter2 router, int requestId,
+ long managerRequestId, RoutingSessionInfo oldSession,
MediaRoute2Info route, Bundle sessionHints) {
Objects.requireNonNull(router, "router must not be null");
+ Objects.requireNonNull(oldSession, "oldSession must not be null");
Objects.requireNonNull(route, "route must not be null");
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- requestCreateSessionWithRouter2Locked(requestId, router, route, sessionHints);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- public void notifySessionHintsForCreatingSession(IMediaRouter2 router,
- long uniqueRequestId, MediaRoute2Info route, Bundle sessionHints) {
- Objects.requireNonNull(router, "router must not be null");
- Objects.requireNonNull(route, "route must not be null");
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- notifySessionHintsForCreatingSessionLocked(uniqueRequestId,
- router, route, sessionHints);
+ requestCreateSessionWithRouter2Locked(requestId, managerRequestId,
+ router, oldSession, route, sessionHints);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -417,16 +404,14 @@ class MediaRouter2ServiceImpl {
}
public void requestCreateSessionWithManager(IMediaRouter2Manager manager, int requestId,
- String packageName, MediaRoute2Info route) {
+ RoutingSessionInfo oldSession, MediaRoute2Info route) {
Objects.requireNonNull(manager, "manager must not be null");
- if (TextUtils.isEmpty(packageName)) {
- throw new IllegalArgumentException("packageName must not be empty");
- }
+ Objects.requireNonNull(oldSession, "oldSession must not be null");
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- requestCreateSessionWithManagerLocked(requestId, manager, packageName, route);
+ requestCreateSessionWithManagerLocked(requestId, manager, oldSession, route);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -638,7 +623,8 @@ class MediaRouter2ServiceImpl {
}
}
- private void requestCreateSessionWithRouter2Locked(int requestId, @NonNull IMediaRouter2 router,
+ private void requestCreateSessionWithRouter2Locked(int requestId, long managerRequestId,
+ @NonNull IMediaRouter2 router, @NonNull RoutingSessionInfo oldSession,
@NonNull MediaRoute2Info route, @Nullable Bundle sessionHints) {
final IBinder binder = router.asBinder();
final RouterRecord routerRecord = mAllRouterRecords.get(binder);
@@ -647,41 +633,60 @@ class MediaRouter2ServiceImpl {
return;
}
- if (route.isSystemRoute() && !routerRecord.mHasModifyAudioRoutingPermission
- && !TextUtils.equals(route.getId(),
- routerRecord.mUserRecord.mHandler.mSystemProvider.getDefaultRoute().getId())) {
- Slog.w(TAG, "MODIFY_AUDIO_ROUTING permission is required to transfer to"
- + route);
- routerRecord.mUserRecord.mHandler.notifySessionCreationFailedToRouter(
- routerRecord, requestId);
- return;
+ if (managerRequestId != MediaRoute2ProviderService.REQUEST_ID_NONE) {
+ ManagerRecord manager = routerRecord.mUserRecord.mHandler.findManagerWithId(
+ toRequesterId(managerRequestId));
+ if (manager == null || manager.mLastSessionCreationRequest == null) {
+ Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
+ + "Ignoring unknown request.");
+ routerRecord.mUserRecord.mHandler.notifySessionCreationFailedToRouter(
+ routerRecord, requestId);
+ return;
+ }
+ if (!TextUtils.equals(manager.mLastSessionCreationRequest.mOldSession.getId(),
+ oldSession.getId())) {
+ Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
+ + "Ignoring unmatched routing session.");
+ routerRecord.mUserRecord.mHandler.notifySessionCreationFailedToRouter(
+ routerRecord, requestId);
+ return;
+ }
+ if (!TextUtils.equals(manager.mLastSessionCreationRequest.mRoute.getId(),
+ route.getId())) {
+ // When media router has no permission
+ if (!routerRecord.mHasModifyAudioRoutingPermission
+ && manager.mLastSessionCreationRequest.mRoute.isSystemRoute()
+ && route.isSystemRoute()) {
+ route = manager.mLastSessionCreationRequest.mRoute;
+ } else {
+ Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
+ + "Ignoring unmatched route.");
+ routerRecord.mUserRecord.mHandler.notifySessionCreationFailedToRouter(
+ routerRecord, requestId);
+ return;
+ }
+ }
+ manager.mLastSessionCreationRequest = null;
+ } else {
+ if (route.isSystemRoute() && !routerRecord.mHasModifyAudioRoutingPermission
+ && !TextUtils.equals(route.getId(),
+ routerRecord.mUserRecord.mHandler.mSystemProvider.getDefaultRoute().getId())) {
+ Slog.w(TAG, "MODIFY_AUDIO_ROUTING permission is required to transfer to"
+ + route);
+ routerRecord.mUserRecord.mHandler.notifySessionCreationFailedToRouter(
+ routerRecord, requestId);
+ return;
+ }
}
long uniqueRequestId = toUniqueRequestId(routerRecord.mRouterId, requestId);
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::requestCreateSessionWithRouter2OnHandler,
routerRecord.mUserRecord.mHandler,
- uniqueRequestId, routerRecord, route,
+ uniqueRequestId, managerRequestId, routerRecord, oldSession, route,
sessionHints));
}
- private void notifySessionHintsForCreatingSessionLocked(long uniqueRequestId,
- @NonNull IMediaRouter2 router,
- @NonNull MediaRoute2Info route, @Nullable Bundle sessionHints) {
- final IBinder binder = router.asBinder();
- final RouterRecord routerRecord = mAllRouterRecords.get(binder);
-
- if (routerRecord == null) {
- Slog.w(TAG, "notifySessionHintsForCreatingSessionLocked: Ignoring unknown router.");
- return;
- }
-
- routerRecord.mUserRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::requestCreateSessionWithManagerOnHandler,
- routerRecord.mUserRecord.mHandler,
- uniqueRequestId, routerRecord, route, sessionHints));
- }
-
private void selectRouteWithRouter2Locked(@NonNull IMediaRouter2 router,
@NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
final IBinder binder = router.asBinder();
@@ -853,27 +858,46 @@ class MediaRouter2ServiceImpl {
private void requestCreateSessionWithManagerLocked(int requestId,
@NonNull IMediaRouter2Manager manager,
- @NonNull String packageName, @NonNull MediaRoute2Info route) {
+ @NonNull RoutingSessionInfo oldSession, @NonNull MediaRoute2Info route) {
ManagerRecord managerRecord = mAllManagerRecords.get(manager.asBinder());
if (managerRecord == null) {
return;
}
+ String packageName = oldSession.getClientPackageName();
+
RouterRecord routerRecord = managerRecord.mUserRecord.findRouterRecordLocked(packageName);
if (routerRecord == null) {
Slog.w(TAG, "requestCreateSessionWithManagerLocked: Ignoring session creation for "
+ "unknown router.");
+ try {
+ managerRecord.mManager.notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "requestCreateSessionWithManagerLocked: Failed to notify failure. "
+ + "Manager probably died.");
+ }
return;
}
long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
+ if (managerRecord.mLastSessionCreationRequest != null) {
+ managerRecord.mUserRecord.mHandler.notifyRequestFailedToManager(
+ managerRecord.mManager,
+ toOriginalRequestId(managerRecord.mLastSessionCreationRequest
+ .mManagerRequestId),
+ REASON_UNKNOWN_ERROR);
+ managerRecord.mLastSessionCreationRequest = null;
+ }
+ managerRecord.mLastSessionCreationRequest = new SessionCreationRequest(routerRecord,
+ MediaRoute2ProviderService.REQUEST_ID_NONE, uniqueRequestId,
+ oldSession, route);
// Before requesting to the provider, get session hints from the media router.
// As a return, media router will request to create a session.
routerRecord.mUserRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::getSessionHintsForCreatingSessionOnHandler,
+ obtainMessage(UserHandler::requestRouterCreateSessionOnHandler,
routerRecord.mUserRecord.mHandler,
- uniqueRequestId, routerRecord, managerRecord, route));
+ uniqueRequestId, routerRecord, managerRecord, oldSession, route));
}
private void selectRouteWithManagerLocked(int requestId, @NonNull IMediaRouter2Manager manager,
@@ -887,7 +911,7 @@ class MediaRouter2ServiceImpl {
// Can be null if the session is system's or RCN.
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
- .findRouterforSessionLocked(uniqueSessionId);
+ .findRouterWithSessionLocked(uniqueSessionId);
long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
managerRecord.mUserRecord.mHandler.sendMessage(
@@ -908,7 +932,7 @@ class MediaRouter2ServiceImpl {
// Can be null if the session is system's or RCN.
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
- .findRouterforSessionLocked(uniqueSessionId);
+ .findRouterWithSessionLocked(uniqueSessionId);
long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
managerRecord.mUserRecord.mHandler.sendMessage(
@@ -929,7 +953,7 @@ class MediaRouter2ServiceImpl {
// Can be null if the session is system's or RCN.
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
- .findRouterforSessionLocked(uniqueSessionId);
+ .findRouterWithSessionLocked(uniqueSessionId);
long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
managerRecord.mUserRecord.mHandler.sendMessage(
@@ -966,7 +990,7 @@ class MediaRouter2ServiceImpl {
}
RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
- .findRouterforSessionLocked(uniqueSessionId);
+ .findRouterWithSessionLocked(uniqueSessionId);
long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
managerRecord.mUserRecord.mHandler.sendMessage(
@@ -1097,6 +1121,7 @@ class MediaRouter2ServiceImpl {
public final int mPid;
public final String mPackageName;
public final int mManagerId;
+ public SessionCreationRequest mLastSessionCreationRequest;
ManagerRecord(UserRecord userRecord, IMediaRouter2Manager manager,
int uid, int pid, String packageName) {
@@ -1222,10 +1247,20 @@ class MediaRouter2ServiceImpl {
}
@Nullable
- public RouterRecord findRouterforSessionLocked(@NonNull String uniqueSessionId) {
+ public RouterRecord findRouterWithSessionLocked(@NonNull String uniqueSessionId) {
return mSessionToRouterMap.get(uniqueSessionId);
}
+ @Nullable
+ public ManagerRecord findManagerWithId(int managerId) {
+ for (ManagerRecord manager : getManagerRecords()) {
+ if (manager.mManagerId == managerId) {
+ return manager;
+ }
+ }
+ return null;
+ }
+
private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) {
int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId());
MediaRoute2ProviderInfo currentInfo = provider.getProviderInfo();
@@ -1318,26 +1353,28 @@ class MediaRouter2ServiceImpl {
return -1;
}
- private void getSessionHintsForCreatingSessionOnHandler(long uniqueRequestId,
+ private void requestRouterCreateSessionOnHandler(long uniqueRequestId,
@NonNull RouterRecord routerRecord, @NonNull ManagerRecord managerRecord,
- @NonNull MediaRoute2Info route) {
- SessionCreationRequest request =
- new SessionCreationRequest(routerRecord, uniqueRequestId, route, managerRecord);
- mSessionCreationRequests.add(request);
-
+ @NonNull RoutingSessionInfo oldSession, @NonNull MediaRoute2Info route) {
try {
- routerRecord.mRouter.getSessionHintsForCreatingSession(uniqueRequestId, route);
+ if (route.isSystemRoute() && !routerRecord.mHasModifyAudioRoutingPermission) {
+ routerRecord.mRouter.requestCreateSessionByManager(uniqueRequestId,
+ oldSession, mSystemProvider.getDefaultRoute());
+ } else {
+ routerRecord.mRouter.requestCreateSessionByManager(uniqueRequestId,
+ oldSession, route);
+ }
} catch (RemoteException ex) {
Slog.w(TAG, "getSessionHintsForCreatingSessionOnHandler: "
+ "Failed to request. Router probably died.", ex);
- mSessionCreationRequests.remove(request);
notifyRequestFailedToManager(managerRecord.mManager,
toOriginalRequestId(uniqueRequestId), REASON_UNKNOWN_ERROR);
}
}
private void requestCreateSessionWithRouter2OnHandler(long uniqueRequestId,
- @NonNull RouterRecord routerRecord,
+ long managerRequestId, @NonNull RouterRecord routerRecord,
+ @NonNull RoutingSessionInfo oldSession,
@NonNull MediaRoute2Info route, @Nullable Bundle sessionHints) {
final MediaRoute2Provider provider = findProvider(route.getProviderId());
@@ -1350,49 +1387,14 @@ class MediaRouter2ServiceImpl {
}
SessionCreationRequest request =
- new SessionCreationRequest(routerRecord, uniqueRequestId, route, null);
+ new SessionCreationRequest(routerRecord, uniqueRequestId,
+ managerRequestId, oldSession, route);
mSessionCreationRequests.add(request);
provider.requestCreateSession(uniqueRequestId, routerRecord.mPackageName,
route.getOriginalId(), sessionHints);
}
- private void requestCreateSessionWithManagerOnHandler(long uniqueRequestId,
- @NonNull RouterRecord routerRecord,
- @NonNull MediaRoute2Info route, @Nullable Bundle sessionHints) {
- SessionCreationRequest matchingRequest = null;
- for (SessionCreationRequest request : mSessionCreationRequests) {
- if (request.mUniqueRequestId == uniqueRequestId) {
- matchingRequest = request;
- break;
- }
- }
- if (matchingRequest == null) {
- Slog.w(TAG, "requestCreateSessionWithManagerOnHandler: "
- + "Ignoring an unknown session creation request.");
- return;
- }
-
- if (!TextUtils.equals(matchingRequest.mRoute.getId(), route.getId())) {
- Slog.w(TAG, "requestCreateSessionWithManagerOnHandler: "
- + "The given route is different from the requested route.");
- return;
- }
-
- final MediaRoute2Provider provider = findProvider(route.getProviderId());
- if (provider == null) {
- Slog.w(TAG, "requestCreateSessionWithManagerOnHandler: Ignoring session "
- + "creation request since no provider found for given route=" + route);
- mSessionCreationRequests.remove(matchingRequest);
- notifyRequestFailedToManager(matchingRequest.mRequestedManagerRecord.mManager,
- toOriginalRequestId(uniqueRequestId), REASON_ROUTE_NOT_AVAILABLE);
- return;
- }
-
- provider.requestCreateSession(uniqueRequestId, routerRecord.mPackageName,
- route.getOriginalId(), sessionHints);
- }
-
// routerRecord can be null if the session is system's or RCN.
private void selectRouteOnHandler(long uniqueRequestId, @Nullable RouterRecord routerRecord,
@NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
@@ -1539,25 +1541,23 @@ class MediaRouter2ServiceImpl {
private void onSessionCreatedOnHandler(@NonNull MediaRoute2Provider provider,
long uniqueRequestId, @NonNull RoutingSessionInfo sessionInfo) {
- notifySessionCreatedToManagers(getManagers(),
- toOriginalRequestId(uniqueRequestId), sessionInfo);
-
- if (uniqueRequestId == REQUEST_ID_NONE) {
- // The session is created without any matching request.
- return;
- }
-
SessionCreationRequest matchingRequest = null;
for (SessionCreationRequest request : mSessionCreationRequests) {
if (request.mUniqueRequestId == uniqueRequestId
&& TextUtils.equals(
- request.mRoute.getProviderId(), provider.getUniqueId())) {
+ request.mRoute.getProviderId(), provider.getUniqueId())) {
matchingRequest = request;
break;
}
}
+ long managerRequestId = (matchingRequest == null)
+ ? MediaRoute2ProviderService.REQUEST_ID_NONE
+ : matchingRequest.mManagerRequestId;
+ // Managers should know created session even if it's not requested.
+ notifySessionCreatedToManagers(managerRequestId, sessionInfo);
+
if (matchingRequest == null) {
Slog.w(TAG, "Ignoring session creation result for unknown request. "
+ "uniqueRequestId=" + uniqueRequestId + ", sessionInfo=" + sessionInfo);
@@ -1565,12 +1565,14 @@ class MediaRouter2ServiceImpl {
}
mSessionCreationRequests.remove(matchingRequest);
-
- if (sessionInfo == null) {
- // Failed
- notifySessionCreationFailedToRouter(matchingRequest.mRouterRecord,
- toOriginalRequestId(uniqueRequestId));
- return;
+ // Not to show old session
+ MediaRoute2Provider oldProvider =
+ findProvider(matchingRequest.mOldSession.getProviderId());
+ if (oldProvider != null) {
+ oldProvider.prepareReleaseSession(matchingRequest.mOldSession.getId());
+ } else {
+ Slog.w(TAG, "onSessionCreatedOnHandler: Can't find provider for an old session. "
+ + "session=" + matchingRequest.mOldSession);
}
String originalRouteId = matchingRequest.mRoute.getId();
@@ -1645,23 +1647,17 @@ class MediaRouter2ServiceImpl {
}
final int requesterId = toRequesterId(uniqueRequestId);
- for (ManagerRecord manager : getManagerRecords()) {
- if (manager.mManagerId == requesterId) {
- notifyRequestFailedToManager(
- manager.mManager, toOriginalRequestId(uniqueRequestId), reason);
- return;
- }
+ ManagerRecord manager = findManagerWithId(requesterId);
+ if (manager != null) {
+ notifyRequestFailedToManager(
+ manager.mManager, toOriginalRequestId(uniqueRequestId), reason);
+ return;
}
// Currently, only the manager can get notified of failures.
// TODO: Notify router too when the related callback is introduced.
}
- // TODO(b/157873556): Find a way to prevent providers from notifying error on random reqID.
- // Possible solutions can be:
- // 1) Record the other type of requests too (not only session creation request)
- // 2) Throw exception on providers when they try to notify error on
- // random uniqueRequestId.
private boolean handleSessionCreationRequestFailed(@NonNull MediaRoute2Provider provider,
long uniqueRequestId, int reason) {
// Check whether the failure is about creating a session
@@ -1683,12 +1679,16 @@ class MediaRouter2ServiceImpl {
// Notify the requester about the failure.
// The call should be made by either MediaRouter2 or MediaRouter2Manager.
- if (matchingRequest.mRequestedManagerRecord == null) {
+ if (matchingRequest.mManagerRequestId == MediaRouter2Manager.REQUEST_ID_NONE) {
notifySessionCreationFailedToRouter(
matchingRequest.mRouterRecord, toOriginalRequestId(uniqueRequestId));
} else {
- notifyRequestFailedToManager(matchingRequest.mRequestedManagerRecord.mManager,
- toOriginalRequestId(uniqueRequestId), reason);
+ final int requesterId = toRequesterId(matchingRequest.mManagerRequestId);
+ ManagerRecord manager = findManagerWithId(requesterId);
+ if (manager != null) {
+ notifyRequestFailedToManager(manager.mManager,
+ toOriginalRequestId(matchingRequest.mManagerRequestId), reason);
+ }
}
return true;
}
@@ -1921,14 +1921,19 @@ class MediaRouter2ServiceImpl {
}
}
- private void notifySessionCreatedToManagers(@NonNull List<IMediaRouter2Manager> managers,
- int requestId, @NonNull RoutingSessionInfo sessionInfo) {
- for (IMediaRouter2Manager manager : managers) {
+ private void notifySessionCreatedToManagers(long managerRequestId,
+ @NonNull RoutingSessionInfo session) {
+ int requesterId = toRequesterId(managerRequestId);
+ int originalRequestId = toOriginalRequestId(managerRequestId);
+
+ for (ManagerRecord manager : getManagerRecords()) {
try {
- manager.notifySessionCreated(requestId, sessionInfo);
+ manager.mManager.notifySessionCreated(
+ ((manager.mManagerId == requesterId) ? originalRequestId :
+ MediaRouter2Manager.REQUEST_ID_NONE), session);
} catch (RemoteException ex) {
Slog.w(TAG, "notifySessionCreatedToManagers: "
- + "failed to notify. Manager probably died.", ex);
+ + "Failed to notify. Manager probably died.", ex);
}
}
}
@@ -2014,7 +2019,7 @@ class MediaRouter2ServiceImpl {
}
mUserRecord.mCompositeDiscoveryPreference =
new RouteDiscoveryPreference.Builder(discoveryPreferences)
- .build();
+ .build();
}
for (MediaRoute2Provider provider : mRouteProviders) {
provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
@@ -2030,21 +2035,22 @@ class MediaRouter2ServiceImpl {
return null;
}
- final class SessionCreationRequest {
- public final RouterRecord mRouterRecord;
- public final long mUniqueRequestId;
- public final MediaRoute2Info mRoute;
- public final ManagerRecord mRequestedManagerRecord;
-
- // requestedManagerRecord is not null only when the request is made by manager.
- SessionCreationRequest(@NonNull RouterRecord routerRecord, long uniqueRequestId,
- @NonNull MediaRoute2Info route,
- @Nullable ManagerRecord requestedManagerRecord) {
- mRouterRecord = routerRecord;
- mUniqueRequestId = uniqueRequestId;
- mRoute = route;
- mRequestedManagerRecord = requestedManagerRecord;
- }
+ }
+ static final class SessionCreationRequest {
+ public final RouterRecord mRouterRecord;
+ public final long mUniqueRequestId;
+ public final long mManagerRequestId;
+ public final RoutingSessionInfo mOldSession;
+ public final MediaRoute2Info mRoute;
+
+ SessionCreationRequest(@NonNull RouterRecord routerRecord, long uniqueRequestId,
+ long managerRequestId, @NonNull RoutingSessionInfo oldSession,
+ @NonNull MediaRoute2Info route) {
+ mRouterRecord = routerRecord;
+ mUniqueRequestId = uniqueRequestId;
+ mManagerRequestId = managerRequestId;
+ mOldSession = oldSession;
+ mRoute = route;
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 3337b480d6a8..0e52a67c8d39 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -481,16 +481,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
public void requestCreateSessionWithRouter2(IMediaRouter2 router, int requestId,
+ long managerRequestId, RoutingSessionInfo oldSession,
MediaRoute2Info route, Bundle sessionHints) {
- mService2.requestCreateSessionWithRouter2(router, requestId, route, sessionHints);
- }
-
- // Binder call
- @Override
- public void notifySessionHintsForCreatingSession(IMediaRouter2 router,
- long uniqueRequestId, MediaRoute2Info route, Bundle sessionHints) {
- mService2.notifySessionHintsForCreatingSession(router,
- uniqueRequestId, route, sessionHints);
+ mService2.requestCreateSessionWithRouter2(router, requestId, managerRequestId,
+ oldSession, route, sessionHints);
}
// Binder call
@@ -558,8 +552,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
public void requestCreateSessionWithManager(IMediaRouter2Manager manager,
- int requestId, String packageName, MediaRoute2Info route) {
- mService2.requestCreateSessionWithManager(manager, requestId, packageName, route);
+ int requestId, RoutingSessionInfo oldSession, MediaRoute2Info route) {
+ mService2.requestCreateSessionWithManager(manager, requestId, oldSession, route);
}
// Binder call
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 42d4c88959bd..2c089ca8300e 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -222,6 +222,11 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
// Do nothing since we don't support grouping volume yet.
}
+ @Override
+ public void prepareReleaseSession(String sessionId) {
+ // Do nothing since the system session persists.
+ }
+
public MediaRoute2Info getDefaultRoute() {
return mDefaultRoute;
}
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 8a7702efcba8..3a203d52edbe 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -280,11 +280,15 @@ public class AppsFilter {
@Override
public void onCompatChange(String packageName) {
- updateEnabledState(mPmInternal.getPackage(packageName));
+ AndroidPackage pkg = mPmInternal.getPackage(packageName);
+ if (pkg == null) {
+ return;
+ }
+ updateEnabledState(pkg);
mAppsFilter.updateShouldFilterCacheForPackage(packageName);
}
- private void updateEnabledState(AndroidPackage pkg) {
+ private void updateEnabledState(@NonNull AndroidPackage pkg) {
// TODO(b/135203078): Do not use toAppInfo
final boolean enabled = mInjector.getCompatibility().isChangeEnabledInternal(
PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
@@ -297,12 +301,12 @@ public class AppsFilter {
@Override
public void updatePackageState(PackageSetting setting, boolean removed) {
- final boolean enableLogging =
+ final boolean enableLogging = setting.pkg != null &&
!removed && (setting.pkg.isTestOnly() || setting.pkg.isDebuggable());
enableLogging(setting.appId, enableLogging);
if (removed) {
- mDisabledPackages.remove(setting.pkg.getPackageName());
- } else {
+ mDisabledPackages.remove(setting.name);
+ } else if (setting.pkg != null) {
updateEnabledState(setting.pkg);
}
}
@@ -495,10 +499,15 @@ public class AppsFilter {
* Adds a package that should be considered when filtering visibility between apps.
*
* @param newPkgSetting the new setting being added
+ * @param isReplace if the package is being replaced and may need extra cleanup.
*/
- public void addPackage(PackageSetting newPkgSetting) {
+ public void addPackage(PackageSetting newPkgSetting, boolean isReplace) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
try {
+ if (isReplace) {
+ // let's first remove any prior rules for this package
+ removePackage(newPkgSetting);
+ }
mStateProvider.runWithState((settings, users) -> {
addPackageInternal(newPkgSetting, settings);
if (mShouldFilterCache != null) {
@@ -578,8 +587,9 @@ public class AppsFilter {
}
}
// if either package instruments the other, mark both as visible to one another
- if (pkgInstruments(newPkgSetting, existingSetting)
- || pkgInstruments(existingSetting, newPkgSetting)) {
+ if (newPkgSetting.pkg != null && existingSetting.pkg != null
+ && (pkgInstruments(newPkgSetting.pkg, existingSetting.pkg)
+ || pkgInstruments(existingSetting.pkg, newPkgSetting.pkg))) {
mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
}
@@ -777,12 +787,20 @@ public class AppsFilter {
}
/**
+ * Equivalent to calling {@link #addPackage(PackageSetting, boolean)} with {@code isReplace}
+ * equal to {@code false}.
+ * @see AppsFilter#addPackage(PackageSetting, boolean)
+ */
+ public void addPackage(PackageSetting newPkgSetting) {
+ addPackage(newPkgSetting, false /* isReplace */);
+ }
+
+ /**
* Removes a package for consideration when filtering visibility between apps.
*
* @param setting the setting of the package being removed.
*/
public void removePackage(PackageSetting setting) {
- removeAppIdFromVisibilityCache(setting.appId);
mStateProvider.runWithState((settings, users) -> {
final int userCount = users.length;
for (int u = 0; u < userCount; u++) {
@@ -805,17 +823,7 @@ public class AppsFilter {
mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
}
- // re-add other shared user members to re-establish visibility between them and other
- // packages
- if (setting.sharedUser != null) {
- for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
- if (setting.sharedUser.packages.valueAt(i) == setting) {
- continue;
- }
- addPackageInternal(
- setting.sharedUser.packages.valueAt(i), settings);
- }
- }
+ mForceQueryable.remove(setting.appId);
if (setting.pkg != null && !setting.pkg.getProtectedBroadcasts().isEmpty()) {
final String removingPackageName = setting.pkg.getPackageName();
@@ -829,6 +837,21 @@ public class AppsFilter {
mOverlayReferenceMapper.removePkg(setting.name);
mFeatureConfig.updatePackageState(setting, true /*removed*/);
+ // After removing all traces of the package, if it's part of a shared user, re-add other
+ // shared user members to re-establish visibility between them and other packages.
+ // NOTE: this must come after all removals from data structures but before we update the
+ // cache
+ if (setting.sharedUser != null) {
+ for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
+ if (setting.sharedUser.packages.valueAt(i) == setting) {
+ continue;
+ }
+ addPackageInternal(
+ setting.sharedUser.packages.valueAt(i), settings);
+ }
+ }
+
+ removeAppIdFromVisibilityCache(setting.appId);
if (mShouldFilterCache != null && setting.sharedUser != null) {
for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
PackageSetting siblingSetting = setting.sharedUser.packages.valueAt(i);
@@ -840,9 +863,6 @@ public class AppsFilter {
}
}
});
- mForceQueryable.remove(setting.appId);
-
-
}
/**
@@ -1091,16 +1111,14 @@ public class AppsFilter {
}
/** Returns {@code true} if the source package instruments the target package. */
- private static boolean pkgInstruments(PackageSetting source, PackageSetting target) {
+ private static boolean pkgInstruments(
+ @NonNull AndroidPackage source, @NonNull AndroidPackage target) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "pkgInstruments");
- final String packageName = target.pkg.getPackageName();
- final List<ParsedInstrumentation> inst = source.pkg.getInstrumentations();
+ final String packageName = target.getPackageName();
+ final List<ParsedInstrumentation> inst = source.getInstrumentations();
for (int i = ArrayUtils.size(inst) - 1; i >= 0; i--) {
if (Objects.equals(inst.get(i).getTargetPackage(), packageName)) {
- if (DEBUG_LOGGING) {
- log(source, target, "instrumentation");
- }
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dc7ed34fb0be..a9d3a07b4e68 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12368,7 +12368,9 @@ public class PackageManagerService extends IPackageManager.Stub
ksms.addScannedPackageLPw(pkg);
mComponentResolver.addAllComponents(pkg, chatty);
- mAppsFilter.addPackage(pkgSetting);
+ final boolean isReplace =
+ reconciledPkg.prepareResult != null && reconciledPkg.prepareResult.replace;
+ mAppsFilter.addPackage(pkgSetting, isReplace);
// Don't allow ephemeral applications to define new permissions groups.
if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 0dc4d131640c..1a7490e8b327 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2281,7 +2281,7 @@ class PackageManagerShellCommand extends ShellCommand {
if (grant) {
mPermissionManager.grantRuntimePermission(pkg, perm, translatedUserId);
} else {
- mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUserId);
+ mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUserId, null);
}
return 0;
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 515225b1d3be..6cd66c642a06 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -970,19 +970,19 @@ public class StagingManager {
// name and the session we are checking is not a parent session either.
continue;
}
-
- // From here on, stagedSession is a non-parent active staged session
-
// Check if stagedSession has an active parent session or not
if (stagedSession.hasParentSessionId()) {
int parentId = stagedSession.getParentSessionId();
PackageInstallerSession parentSession = mStagedSessions.get(parentId);
- if (parentSession == null || parentSession.isStagedAndInTerminalState()) {
+ if (parentSession == null || parentSession.isStagedAndInTerminalState()
+ || parentSession.isDestroyed()) {
// Parent session has been abandoned or terminated already
continue;
}
}
+ // From here on, stagedSession is a non-parent active staged session
+
// Check if session is one of the active sessions
if (session.sessionId == stagedSession.sessionId) {
Slog.w(TAG, "Session " + session.sessionId + " is already staged");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 1b11e2d0860d..4f0b689996f2 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -29,6 +29,9 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAU
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
@@ -327,13 +330,17 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mPackageManagerInt.writeSettings(true);
}
@Override
- public void onPermissionRevoked(int uid, int userId) {
+ public void onPermissionRevoked(int uid, int userId, String reason) {
mOnPermissionChangeListeners.onPermissionsChanged(uid);
// Critical; after this call the application should never have the permission
mPackageManagerInt.writeSettings(false);
final int appId = UserHandle.getAppId(uid);
- mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
+ if (reason == null) {
+ mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
+ } else {
+ mHandler.post(() -> killUid(appId, userId, reason));
+ }
}
@Override
public void onInstallPermissionRevoked() {
@@ -470,7 +477,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
IActivityManager am = ActivityManager.getService();
if (am != null) {
try {
- am.killUid(appId, userId, reason);
+ am.killUidForPermissionChange(appId, userId, reason);
} catch (RemoteException e) {
/* ignore - same process */
}
@@ -754,9 +761,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
- flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ flagValues &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
}
@@ -1112,13 +1119,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
int queryFlags = 0;
if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
- queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ queryFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
}
if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
- queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ queryFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
}
if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
- queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ queryFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
}
ArrayList<String> whitelistedPermissions = null;
@@ -1280,8 +1287,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
- setWhitelistedRestrictedPermissionsForUser(
- pkg, userId, permissions, Process.myUid(), flags, mDefaultPermissionCallback);
+ setWhitelistedRestrictedPermissionsForUsers(pkg, new int[]{ userId }, permissions,
+ Process.myUid(), flags, mDefaultPermissionCallback);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1526,19 +1533,21 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public void revokeRuntimePermission(String packageName, String permName, int userId) {
+ public void revokeRuntimePermission(String packageName, String permName, int userId,
+ String reason) {
final int callingUid = Binder.getCallingUid();
final boolean overridePolicy =
checkUidPermission(ADJUST_RUNTIME_PERMISSIONS_POLICY, callingUid)
== PackageManager.PERMISSION_GRANTED;
revokeRuntimePermissionInternal(permName, packageName, overridePolicy, callingUid, userId,
- mDefaultPermissionCallback);
+ reason, mDefaultPermissionCallback);
}
// TODO swap permission name and package name
private void revokeRuntimePermissionInternal(String permName, String packageName,
- boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
+ boolean overridePolicy, int callingUid, final int userId, String reason,
+ PermissionCallback callback) {
if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is revoking " + packageName + " "
@@ -1629,7 +1638,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (callback != null) {
callback.onPermissionRevoked(UserHandle.getUid(userId,
- UserHandle.getAppId(pkg.getUid())), userId);
+ UserHandle.getAppId(pkg.getUid())), userId, reason);
}
if (bp.isRuntime()) {
@@ -1703,7 +1712,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mDefaultPermissionCallback.onInstallPermissionGranted();
}
- public void onPermissionRevoked(int uid, int userId) {
+ public void onPermissionRevoked(int uid, int userId, String reason) {
revokedPermissions.add(IntPair.of(uid, userId));
syncUpdatedUsers.add(userId);
@@ -1816,7 +1825,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
} else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
// Otherwise, reset the permission.
revokeRuntimePermissionInternal(permName, packageName, false, Process.SYSTEM_UID,
- userId, delayingPermCallback);
+ userId, null, delayingPermCallback);
}
}
@@ -2297,7 +2306,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
try {
revokeRuntimePermissionInternal(permissionName, packageName,
- false, callingUid, userId, permissionCallback);
+ false, callingUid, userId, null, permissionCallback);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Could not revoke " + permissionName + " from "
+ packageName, e);
@@ -2517,8 +2526,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (permission.isHardOrSoftRestricted()
|| permission.isImmutablyRestricted()) {
permissionsState.updatePermissionFlags(permission, userId,
- PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
- PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
+ FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
+ FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
}
if (targetSdkVersion < Build.VERSION_CODES.M) {
permissionsState.updatePermissionFlags(permission, userId,
@@ -3756,8 +3765,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private void setWhitelistedRestrictedPermissionsForUser(@NonNull AndroidPackage pkg,
- @UserIdInt int userId, @Nullable List<String> permissions, int callingUid,
+ private void setWhitelistedRestrictedPermissionsForUsers(@NonNull AndroidPackage pkg,
+ @UserIdInt int[] userIds, @Nullable List<String> permissions, int callingUid,
@PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
final PermissionsState permissionsState =
PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
@@ -3765,95 +3774,102 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return;
}
- ArraySet<String> oldGrantedRestrictedPermissions = null;
+ SparseArray<ArraySet<String>> oldGrantedRestrictedPermissions = new SparseArray<>();
boolean updatePermissions = false;
-
final int permissionCount = pkg.getRequestedPermissions().size();
- for (int i = 0; i < permissionCount; i++) {
- final String permissionName = pkg.getRequestedPermissions().get(i);
- final BasePermission bp = mSettings.getPermissionLocked(permissionName);
+ for (int i = 0; i < userIds.length; i++) {
+ int userId = userIds[i];
+ for (int j = 0; j < permissionCount; j++) {
+ final String permissionName = pkg.getRequestedPermissions().get(j);
- if (bp == null || !bp.isHardOrSoftRestricted()) {
- continue;
- }
+ final BasePermission bp = mSettings.getPermissionLocked(permissionName);
- if (permissionsState.hasPermission(permissionName, userId)) {
- if (oldGrantedRestrictedPermissions == null) {
- oldGrantedRestrictedPermissions = new ArraySet<>();
+ if (bp == null || !bp.isHardOrSoftRestricted()) {
+ continue;
}
- oldGrantedRestrictedPermissions.add(permissionName);
- }
-
- final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId);
-
- int newFlags = oldFlags;
- int mask = 0;
- int whitelistFlagsCopy = whitelistFlags;
- while (whitelistFlagsCopy != 0) {
- final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
- whitelistFlagsCopy &= ~flag;
- switch (flag) {
- case FLAG_PERMISSION_WHITELIST_SYSTEM: {
- mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- if (permissions != null && permissions.contains(permissionName)) {
- newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- } else {
- newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+
+ if (permissionsState.hasPermission(permissionName, userId)) {
+ if (oldGrantedRestrictedPermissions.get(userId) == null) {
+ oldGrantedRestrictedPermissions.put(userId, new ArraySet<>());
+ }
+ oldGrantedRestrictedPermissions.get(userId).add(permissionName);
+ }
+
+ final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId);
+
+ int newFlags = oldFlags;
+ int mask = 0;
+ int whitelistFlagsCopy = whitelistFlags;
+ while (whitelistFlagsCopy != 0) {
+ final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
+ whitelistFlagsCopy &= ~flag;
+ switch (flag) {
+ case FLAG_PERMISSION_WHITELIST_SYSTEM: {
+ mask |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ if (permissions != null && permissions.contains(permissionName)) {
+ newFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ } else {
+ newFlags &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ }
}
- } break;
- case FLAG_PERMISSION_WHITELIST_UPGRADE: {
- mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
- if (permissions != null && permissions.contains(permissionName)) {
- newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
- } else {
- newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ break;
+ case FLAG_PERMISSION_WHITELIST_UPGRADE: {
+ mask |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ if (permissions != null && permissions.contains(permissionName)) {
+ newFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ } else {
+ newFlags &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ }
}
- } break;
- case FLAG_PERMISSION_WHITELIST_INSTALLER: {
- mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- if (permissions != null && permissions.contains(permissionName)) {
- newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- } else {
- newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ break;
+ case FLAG_PERMISSION_WHITELIST_INSTALLER: {
+ mask |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ if (permissions != null && permissions.contains(permissionName)) {
+ newFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ } else {
+ newFlags &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ }
}
- } break;
+ break;
+ }
}
- }
- if (oldFlags == newFlags) {
- continue;
- }
-
- updatePermissions = true;
+ if (oldFlags == newFlags) {
+ continue;
+ }
- final boolean wasWhitelisted = (oldFlags
- & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
- final boolean isWhitelisted = (newFlags
- & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
+ updatePermissions = true;
+
+ final boolean wasWhitelisted = (oldFlags
+ & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
+ final boolean isWhitelisted = (newFlags
+ & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
+
+ // If the permission is policy fixed as granted but it is no longer
+ // on any of the whitelists we need to clear the policy fixed flag
+ // as whitelisting trumps policy i.e. policy cannot grant a non
+ // grantable permission.
+ if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+ final boolean isGranted = permissionsState.hasPermission(permissionName,
+ userId);
+ if (!isWhitelisted && isGranted) {
+ mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ }
+ }
- // If the permission is policy fixed as granted but it is no longer
- // on any of the whitelists we need to clear the policy fixed flag
- // as whitelisting trumps policy i.e. policy cannot grant a non
- // grantable permission.
- if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
- final boolean isGranted = permissionsState.hasPermission(permissionName, userId);
- if (!isWhitelisted && isGranted) {
- mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
- newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ // If we are whitelisting an app that does not support runtime permissions
+ // we need to make sure it goes through the permission review UI at launch.
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
+ && !wasWhitelisted && isWhitelisted) {
+ mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
}
- }
- // If we are whitelisting an app that does not support runtime permissions
- // we need to make sure it goes through the permission review UI at launch.
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
- && !wasWhitelisted && isWhitelisted) {
- mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
- newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ updatePermissionFlagsInternal(permissionName, pkg.getPackageName(), mask, newFlags,
+ callingUid, userId, false, null /*callback*/);
}
-
- updatePermissionFlagsInternal(permissionName, pkg.getPackageName(), mask, newFlags,
- callingUid, userId, false, null /*callback*/);
}
if (updatePermissions) {
@@ -3861,15 +3877,22 @@ public class PermissionManagerService extends IPermissionManager.Stub {
restorePermissionState(pkg, false, pkg.getPackageName(), callback);
// If this resulted in losing a permission we need to kill the app.
- if (oldGrantedRestrictedPermissions != null) {
- final int oldGrantedCount = oldGrantedRestrictedPermissions.size();
- for (int i = 0; i < oldGrantedCount; i++) {
- final String permission = oldGrantedRestrictedPermissions.valueAt(i);
+ for (int i = 0; i < userIds.length; i++) {
+ int userId = userIds[i];
+ ArraySet<String> oldPermsForUser = oldGrantedRestrictedPermissions.get(userId);
+ if (oldPermsForUser == null) {
+ continue;
+ }
+
+ final int oldGrantedCount = oldPermsForUser.size();
+ for (int j = 0; j < oldGrantedCount; j++) {
+ final String permission = oldPermsForUser.valueAt(j);
// Sometimes we create a new permission state instance during update.
final PermissionsState newPermissionsState =
- PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
+ PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt,
+ pkg);
if (!newPermissionsState.hasPermission(permission, userId)) {
- callback.onPermissionRevoked(pkg.getUid(), userId);
+ callback.onPermissionRevoked(pkg.getUid(), userId, null);
break;
}
}
@@ -4228,7 +4251,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
overridePolicy,
Process.SYSTEM_UID,
userId,
- callback);
+ null, callback);
} catch (IllegalArgumentException e) {
Slog.e(TAG,
"Failed to revoke "
@@ -4624,10 +4647,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
public void setWhitelistedRestrictedPermissions(@NonNull AndroidPackage pkg,
@NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
@PackageManager.PermissionWhitelistFlags int flags) {
- for (int userId : userIds) {
- setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions,
- callingUid, flags, mDefaultPermissionCallback);
- }
+ setWhitelistedRestrictedPermissionsForUsers(pkg, userIds, permissions,
+ callingUid, flags, mDefaultPermissionCallback);
}
@Override
public void setWhitelistedRestrictedPermissions(String packageName,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 4412162a5cc8..2e83b23f57d8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -156,7 +156,7 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
}
public void onInstallPermissionGranted() {
}
- public void onPermissionRevoked(int uid, @UserIdInt int userId) {
+ public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {
}
public void onInstallPermissionRevoked() {
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 3ee5f5097d59..37f088b170eb 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -825,7 +825,15 @@ public final class PermissionPolicyService extends SystemService {
return;
}
- if (pkgInfo == null || pkg == null || pkgInfo.requestedPermissions == null) {
+ if (pkgInfo == null || pkg == null || pkgInfo.applicationInfo == null
+ || pkgInfo.requestedPermissions == null) {
+ return;
+ }
+
+ final int uid = pkgInfo.applicationInfo.uid;
+ if (uid == Process.ROOT_UID || uid == Process.SYSTEM_UID) {
+ // Root and system server always pass permission checks, so don't touch their app
+ // ops to keep compatibility.
return;
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/README.md b/services/core/java/com/android/server/soundtrigger_middleware/README.md
new file mode 100644
index 000000000000..416548d9bc5e
--- /dev/null
+++ b/services/core/java/com/android/server/soundtrigger_middleware/README.md
@@ -0,0 +1,19 @@
+# Sound Trigger Middleware
+TODO: Add component description.
+
+## Notes about thread synchronization
+This component has some tricky thread synchronization considerations due to its layered design and
+due to the fact that it is involved in both in-bound and out-bound calls from / to
+external components. To avoid potential deadlocks, a strict locking order must be ensured whenever
+nesting locks. The order is:
+- `SoundTriggerMiddlewareValidation` lock.
+- Audio policy service lock. This one is external - it should be assumed to be held whenever we're
+ inside the `ExternalCaptureStateTracker.setCaptureState()` call stack *AND* to be acquired from
+ within our calls into `AudioSessionProvider.acquireSession()`.
+- `SoundTriggerModule` lock.
+
+This dictates careful consideration of callbacks going from `SoundTriggerModule` to
+`SoundTriggerMiddlewareValidation` and especially those coming from the `setCaptureState()` path.
+We always invoke those calls outside of the `SoundTriggerModule` lock, so we can lock
+`SoundTriggerMiddlewareValidation`. However, in the `setCaptureState()` case, we have to use atomics
+in `SoundTriggerMiddlewareValidation` and avoid the lock.
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index f4c77a0b88ca..5d25d2cb554d 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -47,6 +47,9 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -328,7 +331,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
}
/** Activity state. */
- Activity activityState = Activity.LOADED;
+ private AtomicInteger mActivityState = new AtomicInteger(Activity.LOADED.ordinal());
/** Human-readable description of the model. */
final String description;
@@ -383,6 +386,14 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
void updateParameterSupport(int modelParam, @Nullable ModelParameterRange range) {
parameterSupport.put(modelParam, range);
}
+
+ Activity getActivityState() {
+ return Activity.values()[mActivityState.get()];
+ }
+
+ void setActivityState(Activity activity) {
+ mActivityState.set(activity.ordinal());
+ }
}
/**
@@ -393,7 +404,13 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
IBinder.DeathRecipient {
private final ISoundTriggerCallback mCallback;
private ISoundTriggerModule mDelegate;
- private @NonNull Map<Integer, ModelState> mLoadedModels = new HashMap<>();
+ // While generally all the fields of this class must be changed under a lock, an exception
+ // is made for the specific case of changing a model state from ACTIVE to LOADED, which
+ // may happen as result of a recognition callback. This would happen atomically and is
+ // necessary in order to avoid deadlocks associated with locking from within callbacks
+ // possibly originating from the audio server.
+ private @NonNull
+ ConcurrentMap<Integer, ModelState> mLoadedModels = new ConcurrentHashMap<>();
private final int mHandle;
private ModuleStatus mState = ModuleStatus.ALIVE;
@@ -476,10 +493,9 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
if (modelState == null) {
throw new IllegalStateException("Invalid handle: " + modelHandle);
}
- if (modelState.activityState
- != ModelState.Activity.LOADED) {
+ if (modelState.getActivityState() != ModelState.Activity.LOADED) {
throw new IllegalStateException("Model with handle: " + modelHandle
- + " has invalid state for unloading: " + modelState.activityState);
+ + " has invalid state for unloading: " + modelState.getActivityState());
}
// From here on, every exception isn't client's fault.
@@ -509,19 +525,21 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
if (modelState == null) {
throw new IllegalStateException("Invalid handle: " + modelHandle);
}
- if (modelState.activityState
- != ModelState.Activity.LOADED) {
+ if (modelState.getActivityState() != ModelState.Activity.LOADED) {
throw new IllegalStateException("Model with handle: " + modelHandle
+ " has invalid state for starting recognition: "
- + modelState.activityState);
+ + modelState.getActivityState());
}
// From here on, every exception isn't client's fault.
try {
+ // Normally, we would set the state after the operation succeeds. However, since
+ // the activity state may be reset outside of the lock, we set it here first,
+ // and reset it in case of exception.
+ modelState.setActivityState(ModelState.Activity.ACTIVE);
mDelegate.startRecognition(modelHandle, config);
- modelState.activityState =
- ModelState.Activity.ACTIVE;
} catch (Exception e) {
+ modelState.setActivityState(ModelState.Activity.LOADED);
throw handleException(e);
}
}
@@ -548,8 +566,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// From here on, every exception isn't client's fault.
try {
mDelegate.stopRecognition(modelHandle);
- modelState.activityState =
- ModelState.Activity.LOADED;
+ modelState.setActivityState(ModelState.Activity.LOADED);
} catch (Exception e) {
throw handleException(e);
}
@@ -719,7 +736,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
for (Map.Entry<Integer, ModelState> entry : mLoadedModels.entrySet()) {
pw.print(entry.getKey());
pw.print('\t');
- pw.print(entry.getValue().activityState.name());
+ pw.print(entry.getValue().getActivityState().name());
pw.print('\t');
pw.print(entry.getValue().description);
pw.println();
@@ -735,48 +752,61 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void onRecognition(int modelHandle, @NonNull RecognitionEvent event) {
- synchronized (SoundTriggerMiddlewareValidation.this) {
- if (event.status != RecognitionStatus.FORCED) {
- mLoadedModels.get(modelHandle).activityState =
- ModelState.Activity.LOADED;
- }
- try {
- mCallback.onRecognition(modelHandle, event);
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback exception.", e);
+ // We cannot obtain a lock on SoundTriggerMiddlewareValidation.this, since this call
+ // might be coming from the audio server (via setCaptureState()) while it is holding
+ // a lock that is also acquired while loading / unloading models. Thus, we require a
+ // strict locking order here, where obtaining our lock must always come first.
+ // To avoid this problem, we use an atomic model activity state. There is a risk of the
+ // model not being in the mLoadedModels map here, since it might have been stopped /
+ // unloaded while the event was in flight.
+ if (event.status != RecognitionStatus.FORCED) {
+ ModelState modelState = mLoadedModels.get(modelHandle);
+ if (modelState != null) {
+ modelState.setActivityState(ModelState.Activity.LOADED);
}
}
+ try {
+ mCallback.onRecognition(modelHandle, event);
+ } catch (RemoteException e) {
+ // Dead client will be handled by binderDied() - no need to handle here.
+ // In any case, client callbacks are considered best effort.
+ Log.e(TAG, "Client callback exception.", e);
+ }
}
@Override
public void onPhraseRecognition(int modelHandle, @NonNull PhraseRecognitionEvent event) {
- synchronized (SoundTriggerMiddlewareValidation.this) {
- if (event.common.status != RecognitionStatus.FORCED) {
- mLoadedModels.get(modelHandle).activityState =
- ModelState.Activity.LOADED;
- }
- try {
- mCallback.onPhraseRecognition(modelHandle, event);
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback exception.", e);
+ // We cannot obtain a lock on SoundTriggerMiddlewareValidation.this, since this call
+ // might be coming from the audio server (via setCaptureState()) while it is holding
+ // a lock that is also acquired while loading / unloading models. Thus, we require a
+ // strict locking order here, where obtaining our lock must always come first.
+ // To avoid this problem, we use an atomic model activity state. There is a risk of the
+ // model not being in the mLoadedModels map here, since it might have been stopped /
+ // unloaded while the event was in flight.
+ if (event.common.status != RecognitionStatus.FORCED) {
+ ModelState modelState = mLoadedModels.get(modelHandle);
+ if (modelState != null) {
+ modelState.setActivityState(ModelState.Activity.LOADED);
}
}
+ try {
+ mCallback.onPhraseRecognition(modelHandle, event);
+ } catch (RemoteException e) {
+ // Dead client will be handled by binderDied() - no need to handle here.
+ // In any case, client callbacks are considered best effort.
+ Log.e(TAG, "Client callback exception.", e);
+ }
}
@Override
public void onRecognitionAvailabilityChange(boolean available) {
- synchronized (SoundTriggerMiddlewareValidation.this) {
- try {
- mCallback.onRecognitionAvailabilityChange(available);
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback exception.", e);
- }
+ // Not locking to avoid deadlocks (not affecting any state).
+ try {
+ mCallback.onRecognitionAvailabilityChange(available);
+ } catch (RemoteException e) {
+ // Dead client will be handled by binderDied() - no need to handle here.
+ // In any case, client callbacks are considered best effort.
+ Log.e(TAG, "Client callback exception.", e);
}
}
@@ -804,10 +834,9 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// Gracefully stop all active recognitions and unload the models.
for (Map.Entry<Integer, ModelState> entry :
mLoadedModels.entrySet()) {
- if (entry.getValue().activityState
- == ModelState.Activity.ACTIVE) {
- mDelegate.stopRecognition(entry.getKey());
- }
+ // Idempotent call, no harm in calling even for models that are already
+ // stopped.
+ mDelegate.stopRecognition(entry.getKey());
mDelegate.unloadModel(entry.getKey());
}
// Detach.
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
index 522e5e189232..f809ed4a4a2b 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
@@ -42,6 +42,7 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -153,19 +154,29 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
*
* @param active true iff external capture is active.
*/
- synchronized void setExternalCaptureState(boolean active) {
- if (mProperties.concurrentCapture) {
- // If we support concurrent capture, we don't care about any of this.
- return;
- }
- mRecognitionAvailable = !active;
- if (!mRecognitionAvailable) {
- // Our module does not support recognition while a capture is active -
- // need to abort all active recognitions.
- for (Session session : mActiveSessions) {
- session.abortActiveRecognitions();
+ void setExternalCaptureState(boolean active) {
+ // We should never invoke callbacks while holding the lock, since this may deadlock with
+ // forward calls. Thus, we first gather all the callbacks we need to invoke while holding
+ // the lock, but invoke them after releasing it.
+ List<Runnable> callbacks = new LinkedList<>();
+
+ synchronized (this) {
+ if (mProperties.concurrentCapture) {
+ // If we support concurrent capture, we don't care about any of this.
+ return;
+ }
+ mRecognitionAvailable = !active;
+ if (!mRecognitionAvailable) {
+ // Our module does not support recognition while a capture is active -
+ // need to abort all active recognitions.
+ for (Session session : mActiveSessions) {
+ session.abortActiveRecognitions(callbacks);
+ }
}
}
+ for (Runnable callback : callbacks) {
+ callback.run();
+ }
for (Session session : mActiveSessions) {
session.notifyRecognitionAvailability();
}
@@ -329,9 +340,18 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
@Override
public void startRecognition(int modelHandle, @NonNull RecognitionConfig config) {
+ // We should never invoke callbacks while holding the lock, since this may deadlock with
+ // forward calls. Thus, we first gather all the callbacks we need to invoke while holding
+ // the lock, but invoke them after releasing it.
+ List<Runnable> callbacks = new LinkedList<>();
+
synchronized (SoundTriggerModule.this) {
checkValid();
- mLoadedModels.get(modelHandle).startRecognition(config);
+ mLoadedModels.get(modelHandle).startRecognition(config, callbacks);
+ }
+
+ for (Runnable callback : callbacks) {
+ callback.run();
}
}
@@ -377,10 +397,12 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
/**
* Abort all currently active recognitions.
+ * @param callbacks Will be appended with a list of callbacks that need to be invoked
+ * after this method returns, without holding the module lock.
*/
- private void abortActiveRecognitions() {
+ private void abortActiveRecognitions(@NonNull List<Runnable> callbacks) {
for (Model model : mLoadedModels.values()) {
- model.abortActiveRecognition();
+ model.abortActiveRecognition(callbacks);
}
}
@@ -475,10 +497,11 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
return mSession.mSessionHandle;
}
- private void startRecognition(@NonNull RecognitionConfig config) {
+ private void startRecognition(@NonNull RecognitionConfig config,
+ @NonNull List<Runnable> callbacks) {
if (!mRecognitionAvailable) {
// Recognition is unavailable - send an abort event immediately.
- notifyAbort();
+ callbacks.add(this::notifyAbort);
return;
}
android.hardware.soundtrigger.V2_3.RecognitionConfig hidlConfig =
@@ -525,8 +548,12 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
ConversionUtil.aidl2hidlModelParameter(modelParam)));
}
- /** Abort the recognition, if active. */
- private void abortActiveRecognition() {
+ /**
+ * Abort the recognition, if active.
+ * @param callbacks Will be appended with a list of callbacks that need to be invoked
+ * after this method returns, without holding the module lock.
+ */
+ private void abortActiveRecognition(List<Runnable> callbacks) {
// If we're inactive, do nothing.
if (getState() != ModelState.ACTIVE) {
return;
@@ -535,7 +562,7 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
stopRecognition();
// Notify the client that recognition has been aborted.
- notifyAbort();
+ callbacks.add(this::notifyAbort);
}
/** Notify the client that recognition has been aborted. */
@@ -577,42 +604,44 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
public void recognitionCallback(
@NonNull ISoundTriggerHwCallback.RecognitionEvent recognitionEvent,
int cookie) {
+ RecognitionEvent aidlEvent =
+ ConversionUtil.hidl2aidlRecognitionEvent(recognitionEvent);
+ aidlEvent.captureSession = mSession.mSessionHandle;
synchronized (SoundTriggerModule.this) {
- RecognitionEvent aidlEvent =
- ConversionUtil.hidl2aidlRecognitionEvent(recognitionEvent);
- aidlEvent.captureSession = mSession.mSessionHandle;
- try {
- mCallback.onRecognition(mHandle, aidlEvent);
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback execption.", e);
- }
if (aidlEvent.status != RecognitionStatus.FORCED) {
setState(ModelState.LOADED);
}
}
+ // The callback must be invoked outside of the lock.
+ try {
+ mCallback.onRecognition(mHandle, aidlEvent);
+ } catch (RemoteException e) {
+ // We're not expecting any exceptions here.
+ throw e.rethrowAsRuntimeException();
+ }
}
@Override
public void phraseRecognitionCallback(
@NonNull ISoundTriggerHwCallback.PhraseRecognitionEvent phraseRecognitionEvent,
int cookie) {
+ PhraseRecognitionEvent aidlEvent =
+ ConversionUtil.hidl2aidlPhraseRecognitionEvent(phraseRecognitionEvent);
+ aidlEvent.common.captureSession = mSession.mSessionHandle;
+
synchronized (SoundTriggerModule.this) {
- PhraseRecognitionEvent aidlEvent =
- ConversionUtil.hidl2aidlPhraseRecognitionEvent(phraseRecognitionEvent);
- aidlEvent.common.captureSession = mSession.mSessionHandle;
- try {
- mCallback.onPhraseRecognition(mHandle, aidlEvent);
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback execption.", e);
- }
if (aidlEvent.common.status != RecognitionStatus.FORCED) {
setState(ModelState.LOADED);
}
}
+
+ // The callback must be invoked outside of the lock.
+ try {
+ mCallback.onPhraseRecognition(mHandle, aidlEvent);
+ } catch (RemoteException e) {
+ // We're not expecting any exceptions here.
+ throw e.rethrowAsRuntimeException();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 802a35560ba5..dbdef2368c7c 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -212,7 +212,7 @@ public class StatsPullAtomService extends SystemService {
private static final int DIMENSION_KEY_SIZE_HARD_LIMIT = 800;
private static final int DIMENSION_KEY_SIZE_SOFT_LIMIT = 500;
private static final long APP_OPS_SAMPLING_INITIALIZATION_DELAY_MILLIS = 45000;
- private static final int APP_OPS_SIZE_ESTIMATE = 5000;
+ private static final int APP_OPS_SIZE_ESTIMATE = 2000;
private static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
/**
@@ -320,8 +320,7 @@ public class StatsPullAtomService extends SystemService {
private StatsPullAtomCallbackImpl mStatsCallbackImpl;
- private final Object mAppOpsSamplingRateLock = new Object();
- @GuardedBy("mAppOpsSamplingRateLock")
+ @GuardedBy("mAttributedAppOpsLock")
private int mAppOpsSamplingRate = 0;
private final Object mDangerousAppOpsListLock = new Object();
@GuardedBy("mDangerousAppOpsListLock")
@@ -2576,11 +2575,17 @@ public class StatsPullAtomService extends SystemService {
lastHighWaterMark, section, true, statsFiles, procStats);
procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
- for (ProtoOutputStream proto : protoStreams) {
- if (proto.getBytes().length > 0) {
+ for (int i = 0; i < protoStreams.length; i++) {
+ byte[] bytes = protoStreams[i].getBytes(); // cache the value
+ if (bytes.length > 0) {
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
- .writeByteArray(proto.getBytes())
+ .writeByteArray(bytes)
+ // This is a shard ID, and is specified in the metric definition to be
+ // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE to
+ // keep all the shards, as it thinks each shard is a different dimension
+ // of data.
+ .writeInt(i)
.build();
pulledData.add(e);
}
@@ -3084,7 +3089,7 @@ public class StatsPullAtomService extends SystemService {
int pullDangerousPermissionStateLocked(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
float samplingRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_PERMISSIONS,
- DANGEROUS_PERMISSION_STATE_SAMPLE_RATE, 0.02f);
+ DANGEROUS_PERMISSION_STATE_SAMPLE_RATE, 0.015f);
Set<Integer> reportedUids = new HashSet<>();
try {
PackageManager pm = mContext.getPackageManager();
@@ -3479,23 +3484,21 @@ public class StatsPullAtomService extends SystemService {
HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
TimeUnit.MILLISECONDS);
- synchronized (mAppOpsSamplingRateLock) {
- if (mAppOpsSamplingRate == 0) {
- mContext.getMainThreadHandler().postDelayed(new Runnable() {
- @Override
- public void run() {
- try {
- estimateAppOpsSamplingRate();
- } catch (Throwable e) {
- Slog.e(TAG, "AppOps sampling ratio estimation failed: ", e);
- synchronized (mAppOpsSamplingRateLock) {
- mAppOpsSamplingRate = min(mAppOpsSamplingRate, 10);
- }
+ if (mAppOpsSamplingRate == 0) {
+ mContext.getMainThreadHandler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ estimateAppOpsSamplingRate();
+ } catch (Throwable e) {
+ Slog.e(TAG, "AppOps sampling ratio estimation failed: ", e);
+ synchronized (mAttributedAppOpsLock) {
+ mAppOpsSamplingRate = min(mAppOpsSamplingRate, 10);
}
}
- }, APP_OPS_SAMPLING_INITIALIZATION_DELAY_MILLIS);
- mAppOpsSamplingRate = 100;
- }
+ }
+ }, APP_OPS_SAMPLING_INITIALIZATION_DELAY_MILLIS);
+ mAppOpsSamplingRate = 100;
}
List<AppOpEntry> opsList =
@@ -3503,9 +3506,7 @@ public class StatsPullAtomService extends SystemService {
int newSamplingRate = sampleAppOps(pulledData, opsList, atomTag, mAppOpsSamplingRate);
- synchronized (mAppOpsSamplingRateLock) {
- mAppOpsSamplingRate = min(mAppOpsSamplingRate, newSamplingRate);
- }
+ mAppOpsSamplingRate = min(mAppOpsSamplingRate, newSamplingRate);
} catch (Throwable t) {
// TODO: catch exceptions at a more granular level
Slog.e(TAG, "Could not read appops", t);
@@ -3544,7 +3545,7 @@ public class StatsPullAtomService extends SystemService {
}
int estimatedSamplingRate = (int) constrain(
appOpsTargetCollectionSize * 100 / estimatedSize, 0, 100);
- synchronized (mAppOpsSamplingRateLock) {
+ synchronized (mAttributedAppOpsLock) {
mAppOpsSamplingRate = min(mAppOpsSamplingRate, estimatedSamplingRate);
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 4ba58bd259fc..39e839dfc7e4 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -52,6 +52,7 @@ import android.view.WindowInsetsController.Appearance;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
@@ -61,6 +62,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.view.AppearanceRegion;
import com.android.server.LocalServices;
import com.android.server.UiThread;
+import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.notification.NotificationDelegate;
import com.android.server.policy.GlobalActionsProvider;
import com.android.server.power.ShutdownThread;
@@ -1402,6 +1404,17 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
+ public void hideCurrentInputMethodForBubbles() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ InputMethodManagerInternal.get().hideCurrentInputMethod(
+ SoftInputShowHideReason.HIDE_BUBBLES);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user,
String packageName) {
enforceStatusBarService();
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index c38d649ada9b..5f6323369d0a 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -115,7 +115,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
private static final String TAG = "UriGrantsManagerService";
// Maximum number of persisted Uri grants a package is allowed
private static final int MAX_PERSISTED_URI_GRANTS = 128;
- private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false;
+ private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true;
private final Object mLock = new Object();
private final H mH;
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 6fbfa68d9309..16ca60d1519b 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -52,6 +52,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.PendingIntentRecord;
+import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.wm.ActivityStarter.DefaultFactory;
import com.android.server.wm.ActivityStarter.Factory;
@@ -402,6 +403,7 @@ public class ActivityStartController {
// potentially acquire activity manager lock that leads to deadlock.
for (int i = 0; i < intents.length; i++) {
Intent intent = intents[i];
+ NeededUriGrants intentGrants = null;
// Refuse possible leaked file descriptors.
if (intent.hasFileDescriptors()) {
@@ -418,6 +420,14 @@ public class ActivityStartController {
0 /* startFlags */, null /* profilerInfo */, userId, filterCallingUid);
aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
+ // Carefully collect grants without holding lock
+ if (aInfo != null) {
+ intentGrants = mSupervisor.mService.mUgmInternal
+ .checkGrantUriPermissionFromIntent(intent, filterCallingUid,
+ aInfo.applicationInfo.packageName,
+ UserHandle.getUserId(aInfo.applicationInfo.uid));
+ }
+
if (aInfo != null) {
if ((aInfo.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
@@ -433,6 +443,7 @@ public class ActivityStartController {
? options
: null;
starters[i] = obtainStarter(intent, reason)
+ .setIntentGrants(intentGrants)
.setCaller(caller)
.setResolvedType(resolvedTypes[i])
.setActivityInfo(aInfo)
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index daa97b56ed66..25842f58579d 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -639,8 +639,14 @@ class ActivityStarter {
mRequest.intent, caller);
}
- // Do not lock the resolving to avoid potential deadlock.
+ // If the caller hasn't already resolved the activity, we're willing
+ // to do so here, but because that may require acquiring the AM lock
+ // as part of calculating the NeededUriGrants, we must never hold
+ // the WM lock here to avoid deadlocking.
if (mRequest.activityInfo == null) {
+ if (Thread.holdsLock(mService.mGlobalLock)) {
+ Slog.wtf(TAG, new IllegalStateException("Caller must not hold WM lock"));
+ }
mRequest.resolveActivity(mSupervisor);
}
@@ -2632,6 +2638,11 @@ class ActivityStarter {
return mRequest.intent;
}
+ ActivityStarter setIntentGrants(NeededUriGrants intentGrants) {
+ mRequest.intentGrants = intentGrants;
+ return this;
+ }
+
ActivityStarter setReason(String reason) {
mRequest.reason = reason;
return this;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index cbd2b3358239..205523b2a119 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6174,12 +6174,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent,
boolean allowBackgroundActivityStart) {
assertPackageMatchesCallingUid(callingPackage);
- synchronized (mGlobalLock) {
- return getActivityStartController().startActivitiesInPackage(uid, realCallingPid,
- realCallingUid, callingPackage, callingFeatureId, intents, resolvedTypes,
- resultTo, options, userId, validateIncomingUser, originatingPendingIntent,
- allowBackgroundActivityStart);
- }
+ return getActivityStartController().startActivitiesInPackage(uid, realCallingPid,
+ realCallingUid, callingPackage, callingFeatureId, intents, resolvedTypes,
+ resultTo, options, userId, validateIncomingUser, originatingPendingIntent,
+ allowBackgroundActivityStart);
}
@Override
@@ -6190,13 +6188,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent,
boolean allowBackgroundActivityStart) {
assertPackageMatchesCallingUid(callingPackage);
- synchronized (mGlobalLock) {
- return getActivityStartController().startActivityInPackage(uid, realCallingPid,
- realCallingUid, callingPackage, callingFeatureId, intent, resolvedType,
- resultTo, resultWho, requestCode, startFlags, options, userId, inTask,
- reason, validateIncomingUser, originatingPendingIntent,
- allowBackgroundActivityStart);
- }
+ return getActivityStartController().startActivityInPackage(uid, realCallingPid,
+ realCallingUid, callingPackage, callingFeatureId, intent, resolvedType,
+ resultTo, resultWho, requestCode, startFlags, options, userId, inTask,
+ reason, validateIncomingUser, originatingPendingIntent,
+ allowBackgroundActivityStart);
}
@Override
@@ -6826,7 +6822,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
mWindowManager.closeSystemDialogs(reason);
- mRootWindowContainer.closeSystemDialogs();
+ mRootWindowContainer.closeSystemDialogActivities(reason);
}
// Call into AM outside the synchronized block.
mAmInternal.broadcastCloseSystemDialogs(reason);
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 8fa811915fc2..dd1d55b2d54d 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -83,7 +83,8 @@ class AppTaskImpl extends IAppTask.Stub {
if (task == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
- return mService.getRecentTasks().createRecentTaskInfo(task);
+ return mService.getRecentTasks().createRecentTaskInfo(task,
+ false /* stripExtras */);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 5e3688029bec..afe40b8d8016 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -210,6 +210,7 @@ import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
+import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.utils.DisplayRotationUtil;
@@ -729,7 +730,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Sets mBehindIme for each window. Windows behind IME can get IME insets.
if (w.mBehindIme != mTmpWindowsBehindIme) {
w.mBehindIme = mTmpWindowsBehindIme;
- mWinInsetsChanged.add(w);
+ if (getInsetsStateController().getRawInsetsState().getSourceOrDefaultVisibility(
+ ITYPE_IME)) {
+ // If IME is invisible, behind IME or not doesn't make the insets different.
+ mWinInsetsChanged.add(w);
+ }
}
if (w == mInputMethodWindow) {
mTmpWindowsBehindIme = true;
@@ -1180,6 +1185,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
activity.onRemovedFromDisplay();
+ if (activity == mFixedRotationLaunchingApp) {
+ setFixedRotationLaunchingAppUnchecked(null);
+ }
}
@Override
@@ -1425,7 +1433,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
@Surface.Rotation
int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
- if (!mWmService.mIsFixedRotationTransformEnabled) {
+ if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
return ROTATION_UNDEFINED;
}
if (r.inMultiWindowMode()
@@ -1453,7 +1461,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r,
boolean checkOpening) {
- if (!mWmService.mIsFixedRotationTransformEnabled) {
+ if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
return false;
}
if (r.isFinishingFixedRotationTransform()) {
@@ -1463,10 +1471,17 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// It has been set and not yet finished.
return true;
}
+ if (!r.occludesParent() || r.isVisible()) {
+ // While entering or leaving a translucent or floating activity (e.g. dialog style),
+ // there is a visible activity in the background. Then it still needs rotation animation
+ // to cover the activity configuration change.
+ return false;
+ }
if (checkOpening) {
- if (!mAppTransition.isTransitionSet() && !mOpeningApps.contains(r)) {
+ if (!mAppTransition.isTransitionSet() || !mOpeningApps.contains(r)) {
// Apply normal rotation animation in case of the activity set different requested
- // orientation without activity switch.
+ // orientation without activity switch, or the transition is unset due to starting
+ // window was transferred ({@link #mSkipAppTransitionAnimation}).
return false;
}
} else if (r != topRunningActivity()) {
@@ -3561,6 +3576,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private void updateImeControlTarget() {
mInputMethodControlTarget = computeImeControlTarget();
mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
+
+ final WindowState win = mInputMethodControlTarget != null
+ ? mInputMethodControlTarget.getWindow() : null;
+ final IBinder token = win != null ? win.mClient.asBinder() : null;
+ // Note: not allowed to call into IMMS with the WM lock held, hence the post.
+ mWmService.mH.post(() ->
+ InputMethodManagerInternal.get().reportImeControl(token)
+ );
}
private void updateImeParent() {
@@ -5622,6 +5645,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
void onStartRecentsAnimation(@NonNull ActivityRecord r) {
mAnimatingRecents = r;
+ if (r.isVisible() && mFocusedApp != null && !mFocusedApp.occludesParent()) {
+ // The recents activity has shown with the orientation determined by the top
+ // activity, keep its current orientation to avoid flicking by the configuration
+ // change of visible activity.
+ return;
+ }
rotateInDifferentOrientationIfNeeded(r);
if (r.hasFixedRotationTransform()) {
// Set the record so we can recognize it to continue to update display orientation
@@ -5680,16 +5709,36 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (r == null || r == mAnimatingRecents) {
return;
}
- if (mFixedRotationLaunchingApp != null
- && mFixedRotationLaunchingApp.hasFixedRotationTransform(r)) {
- // Waiting until all of the associated activities have done animation, or the
- // orientation would be updated too early and cause flickers.
- if (!mFixedRotationLaunchingApp.hasAnimatingFixedRotationTransition()) {
- continueUpdateOrientationForDiffOrienLaunchingApp();
+ if (mFixedRotationLaunchingApp == null) {
+ // In most cases this is a no-op if the activity doesn't have fixed rotation.
+ // Otherwise it could be from finishing recents animation while the display has
+ // different orientation.
+ r.finishFixedRotationTransform();
+ return;
+ }
+ if (mFixedRotationLaunchingApp.hasFixedRotationTransform(r)) {
+ if (mFixedRotationLaunchingApp.hasAnimatingFixedRotationTransition()) {
+ // Waiting until all of the associated activities have done animation, or the
+ // orientation would be updated too early and cause flickering.
+ return;
}
} else {
- r.finishFixedRotationTransform();
+ // Handle a corner case that the task of {@link #mFixedRotationLaunchingApp} is no
+ // longer animating but the corresponding transition finished event won't notify.
+ // E.g. activity A transferred starting window to B, only A will receive transition
+ // finished event. A doesn't have fixed rotation but B is the rotated launching app.
+ final Task task = r.getTask();
+ if (task == null || task != mFixedRotationLaunchingApp.getTask()) {
+ // Different tasks won't be in one activity transition animation.
+ return;
+ }
+ if (task.isAppTransitioning()) {
+ return;
+ // Continue to update orientation because the transition of the top rotated
+ // launching activity is done.
+ }
}
+ continueUpdateOrientationForDiffOrienLaunchingApp();
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 8cfe1cd5e98f..72b014cab2bb 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3782,7 +3782,8 @@ public class DisplayPolicy {
&& (behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
|| behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE)
&& getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
- && win != getNotificationShade();
+ && win != getNotificationShade()
+ && !win.isActivityTypeDream();
}
/**
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 8734b5efa45d..0e2611d1ddb9 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -477,12 +477,11 @@ final class InputMonitor {
mService.getRecentsAnimationController();
final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null
&& recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord);
- if (inputChannel == null || inputWindowHandle == null || w.mRemoved
- || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
+ if (inputWindowHandle == null || w.mRemoved) {
if (w.mWinAnimator.hasSurface()) {
mInputTransaction.setInputWindowInfo(
- w.mWinAnimator.mSurfaceController.getClientViewRootSurface(),
- mInvalidInputWindow);
+ w.mWinAnimator.mSurfaceController.getClientViewRootSurface(),
+ mInvalidInputWindow);
}
// Skip this window because it cannot possibly receive input.
return;
@@ -491,9 +490,23 @@ final class InputMonitor {
final int flags = w.mAttrs.flags;
final int privateFlags = w.mAttrs.privateFlags;
final int type = w.mAttrs.type;
- final boolean hasFocus = w.isFocused();
final boolean isVisible = w.isVisibleLw();
+ // Assign an InputInfo with type to the overlay window which can't receive input event.
+ // This is used to omit Surfaces from occlusion detection.
+ if (inputChannel == null
+ || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
+ if (!w.mWinAnimator.hasSurface()) {
+ return;
+ }
+ populateOverlayInputInfo(inputWindowHandle, w.getName(), type, isVisible);
+ mInputTransaction.setInputWindowInfo(
+ w.mWinAnimator.mSurfaceController.getClientViewRootSurface(),
+ inputWindowHandle);
+ return;
+ }
+
+ final boolean hasFocus = w.isFocused();
if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
if (recentsAnimationController.updateInputConsumerForApp(
mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
@@ -555,6 +568,22 @@ final class InputMonitor {
}
}
+ private static void populateOverlayInputInfo(final InputWindowHandle inputWindowHandle,
+ final String name, final int type, final boolean isVisible) {
+ inputWindowHandle.name = name;
+ inputWindowHandle.layoutParamsType = type;
+ inputWindowHandle.dispatchingTimeoutNanos =
+ WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+ inputWindowHandle.visible = isVisible;
+ inputWindowHandle.canReceiveKeys = false;
+ inputWindowHandle.hasFocus = false;
+ inputWindowHandle.ownerPid = myPid();
+ inputWindowHandle.ownerUid = myUid();
+ inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL;
+ inputWindowHandle.scaleFactor = 1;
+ inputWindowHandle.layoutParamsFlags = FLAG_NOT_TOUCH_MODAL;
+ }
+
/**
* Helper function to generate an InputInfo with type SECURE_SYSTEM_OVERLAY. This input
* info will not have an input channel or be touchable, but is used to omit Surfaces
@@ -564,16 +593,7 @@ final class InputMonitor {
static void setTrustedOverlayInputInfo(SurfaceControl sc, SurfaceControl.Transaction t,
int displayId, String name) {
InputWindowHandle inputWindowHandle = new InputWindowHandle(null, displayId);
- inputWindowHandle.name = name;
- inputWindowHandle.layoutParamsType = TYPE_SECURE_SYSTEM_OVERLAY;
- inputWindowHandle.dispatchingTimeoutNanos = -1;
- inputWindowHandle.visible = true;
- inputWindowHandle.canReceiveKeys = false;
- inputWindowHandle.hasFocus = false;
- inputWindowHandle.ownerPid = myPid();
- inputWindowHandle.ownerUid = myUid();
- inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL;
- inputWindowHandle.scaleFactor = 1;
+ populateOverlayInputInfo(inputWindowHandle, name, TYPE_SECURE_SYSTEM_OVERLAY, true);
t.setInputWindowInfo(sc, inputWindowHandle);
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index c7b91067d59f..254356d673e3 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -482,6 +482,12 @@ class InsetsPolicy {
WindowInsetsAnimation animation,
Bounds bounds) {
}
+
+ @Override
+ public void reportPerceptible(int types, boolean perceptible) {
+ // No-op for now - only client windows report perceptibility for now, with policy
+ // controllers assumed to always be perceptible.
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index e80d5937eb1f..63083faaddb1 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -246,7 +246,7 @@ class InsetsStateController {
// (e.g., z-order) have changed. They can affect the insets states that we dispatch to
// the clients.
for (int i = winInsetsChanged.size() - 1; i >= 0; i--) {
- winInsetsChanged.get(i).notifyInsetsChanged();
+ mDispatchInsetsChanged.accept(winInsetsChanged.get(i));
}
}
winInsetsChanged.clear();
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 4a0da75cdad8..892ee717e21f 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -175,7 +175,7 @@ public class LockTaskController {
* {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
* {@link ActivityManager#LOCK_TASK_MODE_PINNED}
*/
- private int mLockTaskModeState = LOCK_TASK_MODE_NONE;
+ private volatile int mLockTaskModeState = LOCK_TASK_MODE_NONE;
/**
* This is ActivityStackSupervisor's Handler.
@@ -500,24 +500,29 @@ public class LockTaskController {
// This method should only be called on the handler thread
private void performStopLockTask(int userId) {
+ // Update the internal mLockTaskModeState early to avoid the scenario that SysUI queries
+ // mLockTaskModeState (from setStatusBarState) and gets staled state.
+ // TODO: revisit this approach.
+ // The race condition raised above can be addressed by moving this function out of handler
+ // thread, which makes it guarded by ATMS#mGlobalLock as ATMS#getLockTaskModeState.
+ final int oldLockTaskModeState = mLockTaskModeState;
+ mLockTaskModeState = LOCK_TASK_MODE_NONE;
// When lock task ends, we enable the status bars.
try {
- setStatusBarState(LOCK_TASK_MODE_NONE, userId);
- setKeyguardState(LOCK_TASK_MODE_NONE, userId);
- if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
+ setStatusBarState(mLockTaskModeState, userId);
+ setKeyguardState(mLockTaskModeState, userId);
+ if (oldLockTaskModeState == LOCK_TASK_MODE_PINNED) {
lockKeyguardIfNeeded();
}
if (getDevicePolicyManager() != null) {
getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
}
- if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
+ if (oldLockTaskModeState == LOCK_TASK_MODE_PINNED) {
getStatusBarService().showPinningEnterExitToast(false /* entering */);
}
- mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE);
+ mWindowManager.onLockTaskStateChanged(mLockTaskModeState);
} catch (RemoteException ex) {
throw new RuntimeException(ex);
- } finally {
- mLockTaskModeState = LOCK_TASK_MODE_NONE;
}
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 24bb7c8d5560..1b58fc1d2d3e 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -961,7 +961,7 @@ class RecentTasks {
continue;
}
- res.add(createRecentTaskInfo(task));
+ res.add(createRecentTaskInfo(task, true /* stripExtras */));
}
return res;
}
@@ -1832,9 +1832,9 @@ class RecentTasks {
/**
* Creates a new RecentTaskInfo from a Task.
*/
- ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr) {
+ ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras) {
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- tr.fillTaskInfo(rti);
+ tr.fillTaskInfo(rti, stripExtras);
// Fill in some deprecated values
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 45a36e562aac..2d30b737b274 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -40,6 +40,7 @@ import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
+import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
@@ -3121,14 +3122,25 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
return hasVisibleActivities;
}
- void closeSystemDialogs() {
+ void closeSystemDialogActivities(String reason) {
forAllActivities((r) -> {
- if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
- r.finishIfPossible("close-sys", true /* oomAdj */);
+ if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0
+ || shouldCloseAssistant(r, reason)) {
+ r.finishIfPossible(reason, true /* oomAdj */);
}
});
}
+ private boolean shouldCloseAssistant(ActivityRecord r, String reason) {
+ if (!r.isActivityTypeAssistant()) return false;
+ if (reason == SYSTEM_DIALOG_REASON_ASSIST) return false;
+ // When the assistant is configured to be on top of the dream, it will have higher z-order
+ // than other activities. If it is also opaque, it will prevent other activities from
+ // starting. We want to close the assistant on closeSystemDialogs to allow other activities
+ // to start, e.g. on home button press.
+ return mWmService.mAssistantOnTopOfDream;
+ }
+
FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper =
new FinishDisabledPackageActivitiesHelper();
class FinishDisabledPackageActivitiesHelper {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fec484935d68..a7b120942163 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2934,7 +2934,7 @@ class Task extends WindowContainer<WindowContainer> {
final Task rootTask = getRootTask();
final Task topNonOrgTask =
rootTask.mCreatedByOrganizer ? rootTask.getTopMostTask() : rootTask;
- if (isDescendantOf(topNonOrgTask)) {
+ if (this == topNonOrgTask || isDescendantOf(topNonOrgTask)) {
return false;
}
}
@@ -3551,11 +3551,19 @@ class Task extends WindowContainer<WindowContainer> {
}
}
+
/**
* Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the
* task info will not include any extras or clip data.
*/
void fillTaskInfo(TaskInfo info) {
+ fillTaskInfo(info, true /* stripExtras */);
+ }
+
+ /**
+ * Fills in a {@link TaskInfo} with information from this task.
+ */
+ void fillTaskInfo(TaskInfo info, boolean stripExtras) {
getNumRunningActivities(mReuseActivitiesReport);
info.userId = mUserId;
info.stackId = getRootTaskId();
@@ -3566,7 +3574,9 @@ class Task extends WindowContainer<WindowContainer> {
// Make a copy of base intent because this is like a snapshot info.
// Besides, {@link RecentTasks#getRecentTasksImpl} may modify it.
final int baseIntentFlags = baseIntent == null ? 0 : baseIntent.getFlags();
- info.baseIntent = baseIntent == null ? new Intent() : baseIntent.cloneFilter();
+ info.baseIntent = baseIntent == null
+ ? new Intent()
+ : stripExtras ? baseIntent.cloneFilter() : new Intent(baseIntent);
info.baseIntent.setFlags(baseIntentFlags);
info.baseActivity = mReuseActivitiesReport.base != null
? mReuseActivitiesReport.base.intent.getComponent()
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 46761dc81117..7b690383f5f9 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -126,10 +126,6 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
private final RootWindowContainer.FindTaskResult
mTmpFindTaskResult = new RootWindowContainer.FindTaskResult();
- // Indicates whether the Assistant should show on top of the Dream (respectively, above
- // everything else on screen). Otherwise, it will be put under always-on-top stacks.
- private final boolean mAssistantOnTopOfDream;
-
/**
* If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
* stack has been resumed. If stacks are changing position this will hold the old stack until
@@ -155,9 +151,6 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
mDisplayContent = displayContent;
mRootWindowContainer = service.mRoot;
mAtmService = service.mAtmService;
-
- mAssistantOnTopOfDream = mWmService.mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_assistantOnTopOfDream);
}
/**
@@ -392,7 +385,7 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
* @return the priority of the stack
*/
private int getPriority(ActivityStack stack) {
- if (mAssistantOnTopOfDream && stack.isActivityTypeAssistant()) return 4;
+ if (mWmService.mAssistantOnTopOfDream && stack.isActivityTypeAssistant()) return 4;
if (stack.isActivityTypeDream()) return 3;
if (stack.inPinnedWindowingMode()) return 2;
if (stack.isAlwaysOnTop()) return 1;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 3a1619ba11a1..1a6d85547c92 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1897,6 +1897,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
boolean needsZBoost() {
+ if (mNeedsZBoost) return true;
for (int i = 0; i < mChildren.size(); i++) {
if (mChildren.get(i).needsZBoost()) {
return true;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 27864393d23e..564eecf725cc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -415,6 +415,13 @@ public class WindowManagerService extends IWindowManager.Stub
static boolean sEnableTripleBuffering = !SystemProperties.getBoolean(
DISABLE_TRIPLE_BUFFERING_PROPERTY, false);
+ /**
+ * Allows a fullscreen windowing mode activity to launch in its desired orientation directly
+ * when the display has different orientation.
+ */
+ static final boolean ENABLE_FIXED_ROTATION_TRANSFORM =
+ SystemProperties.getBoolean("persist.wm.fixed_rotation_transform", true);
+
// Enums for animation scale update types.
@Retention(RetentionPolicy.SOURCE)
@IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
@@ -431,10 +438,6 @@ public class WindowManagerService extends IWindowManager.Stub
/** System UI can create more window context... */
private static final int SYSTEM_UI_MULTIPLIER = 2;
- // TODO(b/143053092): Remove the settings if it becomes stable.
- private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform";
- boolean mIsFixedRotationTransformEnabled;
-
final WindowManagerConstants mConstants;
final WindowTracing mWindowTracing;
@@ -528,6 +531,10 @@ public class WindowManagerService extends IWindowManager.Stub
final boolean mAllowBootMessages;
+ // Indicates whether the Assistant should show on top of the Dream (respectively, above
+ // everything else on screen). Otherwise, it will be put under always-on-top stacks.
+ final boolean mAssistantOnTopOfDream;
+
final boolean mLimitedAlphaCompositing;
final int mMaxUiWidth;
@@ -761,8 +768,6 @@ public class WindowManagerService extends IWindowManager.Stub
DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM);
private final Uri mRenderShadowsInCompositorUri = Settings.Global.getUriFor(
DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR);
- private final Uri mFixedRotationTransformUri = Settings.Global.getUriFor(
- FIXED_ROTATION_TRANSFORM_SETTING_NAME);
public SettingsObserver() {
super(new Handler());
@@ -787,8 +792,6 @@ public class WindowManagerService extends IWindowManager.Stub
UserHandle.USER_ALL);
resolver.registerContentObserver(mRenderShadowsInCompositorUri, false, this,
UserHandle.USER_ALL);
- resolver.registerContentObserver(mFixedRotationTransformUri, false, this,
- UserHandle.USER_ALL);
}
@Override
@@ -832,11 +835,6 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
- if (mFixedRotationTransformUri.equals(uri)) {
- updateFixedRotationTransform();
- return;
- }
-
@UpdateAnimationScaleMode
final int mode;
if (mWindowAnimationScaleUri.equals(uri)) {
@@ -856,7 +854,6 @@ public class WindowManagerService extends IWindowManager.Stub
void loadSettings() {
updateSystemUiSettings();
updatePointerLocation();
- updateFixedRotationTransform();
}
void updateSystemUiSettings() {
@@ -928,17 +925,6 @@ public class WindowManagerService extends IWindowManager.Stub
mAtmService.mSizeCompatFreeform = sizeCompatFreeform;
}
-
- void updateFixedRotationTransform() {
- final int enabled = Settings.Global.getInt(mContext.getContentResolver(),
- FIXED_ROTATION_TRANSFORM_SETTING_NAME, 2);
- if (enabled == 2) {
- // Make sure who read the settings won't use inconsistent default value.
- Settings.Global.putInt(mContext.getContentResolver(),
- FIXED_ROTATION_TRANSFORM_SETTING_NAME, 1);
- }
- mIsFixedRotationTransformEnabled = enabled != 0;
- }
}
private void setShadowRenderer() {
@@ -1181,6 +1167,8 @@ public class WindowManagerService extends IWindowManager.Stub
com.android.internal.R.bool.config_disableTransitionAnimation);
mPerDisplayFocusEnabled = context.getResources().getBoolean(
com.android.internal.R.bool.config_perDisplayFocusEnabled);
+ mAssistantOnTopOfDream = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistantOnTopOfDream);
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
@@ -5154,8 +5142,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
case WINDOW_STATE_BLAST_SYNC_TIMEOUT: {
synchronized (mGlobalLock) {
- final WindowState ws = (WindowState) msg.obj;
- ws.finishDrawing(null);
+ final WindowState ws = (WindowState) msg.obj;
+ ws.immediatelyNotifyBlastSync();
}
break;
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index fbc5afadac6b..46e1bf04bdbe 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -428,6 +428,9 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
try {
callback.onTransactionReady(mSyncId, mergedTransaction);
} catch (RemoteException e) {
+ // If there's an exception when trying to send the mergedTransaction to the client, we
+ // should immediately apply it here so the transactions aren't lost.
+ mergedTransaction.apply();
}
mTransactionCallbacksByPendingSyncId.remove(mSyncId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 26a1fea1732b..49ef4e46bfeb 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2192,7 +2192,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void removeIfPossible() {
super.removeIfPossible();
removeIfPossible(false /*keepVisibleDeadWindow*/);
- finishDrawing(null);
+ immediatelyNotifyBlastSync();
}
private void removeIfPossible(boolean keepVisibleDeadWindow) {
@@ -5806,7 +5806,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// client will not render when visibility is GONE. Therefore, call finishDrawing here to
// prevent system server from blocking on a window that will not draw.
if (viewVisibility == View.GONE && mUsingBLASTSyncTransaction) {
- finishDrawing(null);
+ immediatelyNotifyBlastSync();
}
}
@@ -5844,7 +5844,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mWinAnimator.finishDrawingLocked(postDrawTransaction);
}
- mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
if (postDrawTransaction != null) {
mBLASTSyncTransaction.merge(postDrawTransaction);
}
@@ -5853,8 +5852,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mWinAnimator.finishDrawingLocked(null);
}
- @VisibleForTesting
- void notifyBlastSyncTransaction() {
+ private void notifyBlastSyncTransaction() {
+ mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
+
if (!mNotifyBlastOnSurfacePlacement || mWaitingListener == null) {
mNotifyBlastOnSurfacePlacement = false;
return;
@@ -5877,6 +5877,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mNotifyBlastOnSurfacePlacement = false;
}
+ void immediatelyNotifyBlastSync() {
+ finishDrawing(null);
+ notifyBlastSyncTransaction();
+ }
+
private boolean requestResizeForBlastSync() {
return useBLASTSync() && !mResizeForBlastSyncReported;
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index c7dac787c653..465a3518ab65 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -3109,9 +3109,7 @@ static jboolean android_location_GnssMeasurementsProvider_start_measurement_coll
result = gnssMeasurementIface_V1_1->setCallback_1_1(cbIface, enableFullTracking);
} else {
if (enableFullTracking == JNI_TRUE) {
- // full tracking mode not supported in 1.0 HAL
- result.assertOk(); // isOk() must be called before result destructor is invoked.
- return JNI_FALSE;
+ ALOGW("Full tracking mode not supported in 1.0 GNSS HAL.");
}
result = gnssMeasurementIface->setCallback(cbIface);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
index e3453a06990f..b2847ce88a2c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
@@ -23,6 +23,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
@@ -81,8 +82,10 @@ public class PendingIntentControllerTest {
doReturn(mIPackageManager).when(() -> AppGlobals.getPackageManager());
when(mIPackageManager.getPackageUid(eq(TEST_PACKAGE_NAME), anyInt(), anyInt())).thenReturn(
TEST_CALLING_UID);
+ ActivityManagerConstants constants = mock(ActivityManagerConstants.class);
+ constants.PENDINGINTENT_WARNING_THRESHOLD = 2000;
mPendingIntentController = new PendingIntentController(Looper.getMainLooper(),
- mUserController);
+ mUserController, constants);
mPendingIntentController.onActivityManagerInternalAdded();
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index de6f55ba1053..0a61c443e0bd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -169,12 +169,13 @@ public class AppOpsServiceTest {
mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
// Note an op that's allowed.
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
// Note another op that's not allowed.
- mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null,
+ false);
loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
@@ -191,7 +192,7 @@ public class AppOpsServiceTest {
mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);
assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
- null)).isEqualTo(MODE_ALLOWED);
+ null, false)).isEqualTo(MODE_ALLOWED);
assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
@@ -199,7 +200,7 @@ public class AppOpsServiceTest {
// Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
- null)).isEqualTo(MODE_ERRORED);
+ null, false)).isEqualTo(MODE_ERRORED);
assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
@@ -210,8 +211,9 @@ public class AppOpsServiceTest {
public void testStatePersistence() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
- mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
+ mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null,
+ false);
mAppOpsService.writeState();
// Create a new app ops service, and initialize its state from XML.
@@ -228,7 +230,7 @@ public class AppOpsServiceTest {
@Test
public void testShutdown() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
mAppOpsService.shutdown();
// Create a new app ops service, and initialize its state from XML.
@@ -243,7 +245,7 @@ public class AppOpsServiceTest {
@Test
public void testGetOpsForPackage() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
// Query all ops
List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
@@ -272,7 +274,7 @@ public class AppOpsServiceTest {
@Test
public void testPackageRemoved() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -287,7 +289,7 @@ public class AppOpsServiceTest {
@Test
public void testPackageRemovedHistoricalOps() throws InterruptedException {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName, null,
@@ -327,7 +329,7 @@ public class AppOpsServiceTest {
@Test
public void testUidRemoved() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -351,12 +353,12 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isEqualTo(MODE_ALLOWED);
+ false, null, false)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -365,7 +367,7 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
}
@Test
@@ -374,12 +376,12 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
}
@Test
@@ -389,12 +391,12 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isEqualTo(MODE_ALLOWED);
+ false, null, false)).isEqualTo(MODE_ALLOWED);
}
@Test
@@ -404,12 +406,12 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isEqualTo(MODE_ALLOWED);
+ false, null, false)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -418,7 +420,7 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
}
@Test
@@ -428,12 +430,12 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isEqualTo(MODE_ALLOWED);
+ false, null, false)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
@@ -442,7 +444,7 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isEqualTo(MODE_ALLOWED);
+ false, null, false)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -451,7 +453,7 @@ public class AppOpsServiceTest {
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
- false, null)).isNotEqualTo(MODE_ALLOWED);
+ false, null, false)).isNotEqualTo(MODE_ALLOWED);
}
private List<PackageOps> getLoggedOps() {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FullScreenMagnificationGestureHandlerTest.java
index 2007d4fff8c1..1cbee12720b0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FullScreenMagnificationGestureHandlerTest.java
@@ -20,6 +20,7 @@ import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
+import static android.view.MotionEvent.ACTION_UP;
import static com.android.server.testutils.TestUtils.strictMock;
@@ -38,11 +39,13 @@ import static org.mockito.Mockito.when;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.Context;
+import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
import android.util.DebugUtils;
import android.view.InputDevice;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -56,6 +59,9 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
import java.util.function.IntConsumer;
/**
@@ -106,6 +112,7 @@ public class FullScreenMagnificationGestureHandlerTest {
// Co-prime x and y, to potentially catch x-y-swapped errors
public static final float DEFAULT_X = 301;
public static final float DEFAULT_Y = 299;
+ public static final PointF DEFAULT_POINT = new PointF(DEFAULT_X, DEFAULT_Y);
private static final int DISPLAY_0 = 0;
@@ -327,6 +334,107 @@ public class FullScreenMagnificationGestureHandlerTest {
});
}
+ @Test
+ public void testTwoFingersOneTap_zoomedState_dispatchMotionEvents() {
+ goFromStateIdleTo(STATE_ZOOMED);
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
+ send(pointerEvent(ACTION_POINTER_UP, DEFAULT_X * 2, DEFAULT_Y));
+ send(upEvent());
+
+ assertIn(STATE_ZOOMED);
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_POINTER_UP));
+ expectedActions.add(Integer.valueOf(ACTION_UP));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+
+ returnToNormalFrom(STATE_ZOOMED);
+ }
+
+ @Test
+ public void testThreeFingersOneTap_zoomedState_dispatchMotionEvents() {
+ goFromStateIdleTo(STATE_ZOOMED);
+ final EventCaptor eventCaptor = new EventCaptor();
+ mMgh.setNext(eventCaptor);
+ PointF pointer1 = DEFAULT_POINT;
+ PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
+ PointF pointer3 = new PointF(DEFAULT_X * 2, DEFAULT_Y);
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}));
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2, pointer3}));
+ send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}));
+ send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}));
+ send(upEvent());
+
+ assertIn(STATE_ZOOMED);
+ final List<Integer> expectedActions = new ArrayList();
+ expectedActions.add(Integer.valueOf(ACTION_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
+ expectedActions.add(Integer.valueOf(ACTION_POINTER_UP));
+ expectedActions.add(Integer.valueOf(ACTION_POINTER_UP));
+ expectedActions.add(Integer.valueOf(ACTION_UP));
+ assertActionsInOrder(eventCaptor.mEvents, expectedActions);
+
+ returnToNormalFrom(STATE_ZOOMED);
+ }
+
+ @Test
+ public void testFirstFingerSwipe_TwoPinterDownAndZoomedState_panningState() {
+ goFromStateIdleTo(STATE_ZOOMED);
+ PointF pointer1 = DEFAULT_POINT;
+ PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}));
+ //The minimum movement to transit to panningState.
+ final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ pointer1.offset(sWipeMinDistance + 1, 0);
+ send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}));
+ assertIn(STATE_PANNING);
+
+ assertIn(STATE_PANNING);
+ returnToNormalFrom(STATE_PANNING);
+ }
+
+ @Test
+ public void testSecondFingerSwipe_TwoPinterDownAndZoomedState_panningState() {
+ goFromStateIdleTo(STATE_ZOOMED);
+ PointF pointer1 = DEFAULT_POINT;
+ PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}));
+ //The minimum movement to transit to panningState.
+ final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ pointer2.offset(sWipeMinDistance + 1, 0);
+ send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}));
+ assertIn(STATE_PANNING);
+
+ assertIn(STATE_PANNING);
+ returnToNormalFrom(STATE_PANNING);
+ }
+
+ private void assertActionsInOrder(List<MotionEvent> actualEvents,
+ List<Integer> expectedActions) {
+ assertTrue(actualEvents.size() == expectedActions.size());
+ final int size = actualEvents.size();
+ for (int i = 0; i < size; i++) {
+ final int expectedAction = expectedActions.get(i);
+ final int actualAction = actualEvents.get(i).getActionMasked();
+ assertTrue(String.format(
+ "%dth action %s is not matched, actual events : %s, ", i,
+ MotionEvent.actionToString(expectedAction), actualEvents),
+ actualAction == expectedAction);
+ }
+ }
+
private void assertZoomsImmediatelyOnSwipeFrom(int state) {
goFromStateIdleTo(state);
swipeAndHold();
@@ -467,6 +575,7 @@ public class FullScreenMagnificationGestureHandlerTest {
goFromStateIdleTo(STATE_ZOOMED);
send(downEvent());
send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
+ fastForward(ViewConfiguration.getTapTimeout());
} break;
case STATE_SCALING_AND_PANNING: {
goFromStateIdleTo(STATE_PANNING);
@@ -619,40 +728,67 @@ public class FullScreenMagnificationGestureHandlerTest {
MotionEvent.ACTION_UP, x, y, 0));
}
+
private MotionEvent pointerEvent(int action, float x, float y) {
- MotionEvent.PointerProperties defPointerProperties = new MotionEvent.PointerProperties();
- defPointerProperties.id = 0;
- defPointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
- MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties();
- pointerProperties.id = 1;
- pointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
-
- MotionEvent.PointerCoords defPointerCoords = new MotionEvent.PointerCoords();
- defPointerCoords.x = DEFAULT_X;
- defPointerCoords.y = DEFAULT_Y;
- MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
- pointerCoords.x = x;
- pointerCoords.y = y;
+ return pointerEvent(action, new PointF[] {DEFAULT_POINT, new PointF(x, y)});
+ }
+
+ private MotionEvent pointerEvent(int action, PointF[] pointersPosition) {
+ final MotionEvent.PointerProperties[] PointerPropertiesArray =
+ new MotionEvent.PointerProperties[pointersPosition.length];
+ for (int i = 0; i < pointersPosition.length; i++) {
+ MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties();
+ pointerProperties.id = i;
+ pointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
+ PointerPropertiesArray[i] = pointerProperties;
+ }
+
+ final MotionEvent.PointerCoords[] pointerCoordsArray =
+ new MotionEvent.PointerCoords[pointersPosition.length];
+ for (int i = 0; i < pointersPosition.length; i++) {
+ MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
+ pointerCoords.x = pointersPosition[i].x;
+ pointerCoords.y = pointersPosition[i].y;
+ pointerCoordsArray[i] = pointerCoords;
+ }
return MotionEvent.obtain(
- /* downTime */ mClock.now(),
- /* eventTime */ mClock.now(),
- /* action */ action,
- /* pointerCount */ 2,
- /* pointerProperties */ new MotionEvent.PointerProperties[] {
- defPointerProperties, pointerProperties},
- /* pointerCoords */ new MotionEvent.PointerCoords[] { defPointerCoords, pointerCoords },
- /* metaState */ 0,
- /* buttonState */ 0,
- /* xPrecision */ 1.0f,
- /* yPrecision */ 1.0f,
- /* deviceId */ 0,
- /* edgeFlags */ 0,
- /* source */ InputDevice.SOURCE_TOUCHSCREEN,
- /* flags */ 0);
+ /* downTime */ mClock.now(),
+ /* eventTime */ mClock.now(),
+ /* action */ action,
+ /* pointerCount */ pointersPosition.length,
+ /* pointerProperties */ PointerPropertiesArray,
+ /* pointerCoords */ pointerCoordsArray,
+ /* metaState */ 0,
+ /* buttonState */ 0,
+ /* xPrecision */ 1.0f,
+ /* yPrecision */ 1.0f,
+ /* deviceId */ 0,
+ /* edgeFlags */ 0,
+ /* source */ InputDevice.SOURCE_TOUCHSCREEN,
+ /* flags */ 0);
}
+
private String stateDump() {
return "\nCurrent state dump:\n" + mMgh + "\n" + mHandler.getPendingMessages();
}
+
+ private class EventCaptor implements EventStreamTransformation {
+ List<MotionEvent> mEvents = new ArrayList<>();
+
+ @Override
+ public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ mEvents.add(event.copy());
+ }
+
+ @Override
+ public void setNext(EventStreamTransformation next) {
+ }
+
+ @Override
+ public EventStreamTransformation getNext() {
+ return null;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 6fe259e7fc85..6a797f31fa55 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -506,7 +506,7 @@ public class ActivityManagerServiceTest {
@Test
public void testDispatchUids_dispatchNeededChanges() throws RemoteException {
when(mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null,
- null, false, null)).thenReturn(AppOpsManager.MODE_ALLOWED);
+ null, false, null, false)).thenReturn(AppOpsManager.MODE_ALLOWED);
final int[] changesToObserve = {
ActivityManager.UID_OBSERVER_PROCSTATE,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
index 8607ec66a5ba..7538468fbe31 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
@@ -17,7 +17,6 @@ package com.android.server.hdmi;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.tv.cec.V1_0.SendMessageResult;
-import android.os.MessageQueue;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.HdmiCecController.NativeWrapper;
@@ -53,13 +52,16 @@ final class FakeNativeWrapper implements NativeWrapper {
private HdmiPortInfo[] mHdmiPortInfo = null;
@Override
- public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
- return 1L;
+ public String nativeInit() {
+ return "[class or subclass of IHdmiCec]@Proxy";
}
@Override
+ public void setCallback(HdmiCecController.HdmiCecCallback callback) {}
+
+ @Override
public int nativeSendCecCommand(
- long controllerPtr, int srcAddress, int dstAddress, byte[] body) {
+ int srcAddress, int dstAddress, byte[] body) {
if (body.length == 0) {
return mPollAddressResponse[dstAddress];
} else {
@@ -69,30 +71,30 @@ final class FakeNativeWrapper implements NativeWrapper {
}
@Override
- public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
+ public int nativeAddLogicalAddress(int logicalAddress) {
return 0;
}
@Override
- public void nativeClearLogicalAddress(long controllerPtr) {}
+ public void nativeClearLogicalAddress() {}
@Override
- public int nativeGetPhysicalAddress(long controllerPtr) {
+ public int nativeGetPhysicalAddress() {
return mMyPhysicalAddress;
}
@Override
- public int nativeGetVersion(long controllerPtr) {
+ public int nativeGetVersion() {
return 0;
}
@Override
- public int nativeGetVendorId(long controllerPtr) {
+ public int nativeGetVendorId() {
return 0;
}
@Override
- public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
+ public HdmiPortInfo[] nativeGetPortInfos() {
if (mHdmiPortInfo == null) {
mHdmiPortInfo = new HdmiPortInfo[1];
mHdmiPortInfo[0] = new HdmiPortInfo(1, 1, 0x1000, true, true, true);
@@ -101,16 +103,16 @@ final class FakeNativeWrapper implements NativeWrapper {
}
@Override
- public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {}
+ public void nativeSetOption(int flag, boolean enabled) {}
@Override
- public void nativeSetLanguage(long controllerPtr, String language) {}
+ public void nativeSetLanguage(String language) {}
@Override
- public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {}
+ public void nativeEnableAudioReturnChannel(int port, boolean flag) {}
@Override
- public boolean nativeIsConnected(long controllerPtr, int port) {
+ public boolean nativeIsConnected(int port) {
return false;
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
new file mode 100644
index 000000000000..b88573ae168a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
+import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(JUnit4.class)
+/** Tests for {@link HdmiCecLocalDeviceTv} class. */
+public class HdmiCecLocalDeviceTvTest {
+
+ private HdmiControlService mHdmiControlService;
+ private HdmiCecController mHdmiCecController;
+ private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
+ private FakeNativeWrapper mNativeWrapper;
+ private Looper mMyLooper;
+ private TestLooper mTestLooper = new TestLooper();
+ private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+ private int mTvPhysicalAddress;
+
+ @Mock
+ private IPowerManager mIPowerManagerMock;
+ @Mock
+ private IThermalService mIThermalServiceMock;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = InstrumentationRegistry.getTargetContext();
+ mMyLooper = mTestLooper.getLooper();
+ PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
+ mIThermalServiceMock, new Handler(mMyLooper));
+ mHdmiControlService =
+ new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+ @Override
+ boolean isControlEnabled() {
+ return true;
+ }
+
+ @Override
+ boolean isTvDevice() {
+ return true;
+ }
+
+ @Override
+ void writeStringSystemProperty(String key, String value) {
+ // do nothing
+ }
+
+ @Override
+ PowerManager getPowerManager() {
+ return powerManager;
+ }
+ };
+
+ mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
+ mHdmiCecLocalDeviceTv.init();
+ mHdmiControlService.setIoLooper(mMyLooper);
+ mNativeWrapper = new FakeNativeWrapper();
+ mHdmiCecController =
+ HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+ mHdmiControlService.setCecController(mHdmiCecController);
+ mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+ mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+ mLocalDevices.add(mHdmiCecLocalDeviceTv);
+ mHdmiControlService.initPortInfo();
+ mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mTvPhysicalAddress = 0x0000;
+ mNativeWrapper.setPhysicalAddress(mTvPhysicalAddress);
+ mTestLooper.dispatchAll();
+ mNativeWrapper.clearResultMessages();
+ }
+
+ @Test
+ public void initialPowerStateIsStandby() {
+ assertThat(mHdmiCecLocalDeviceTv.getPowerStatus()).isEqualTo(
+ HdmiControlManager.POWER_STATUS_STANDBY);
+ }
+
+ @Test
+ public void onAddressAllocated_invokesDeviceDiscovery() {
+ mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
+ mHdmiCecLocalDeviceTv.onAddressAllocated(0, HdmiControlService.INITIATED_BY_BOOT_UP);
+
+ mTestLooper.dispatchAll();
+
+ // Check for for <Give Physical Address> being sent to available device (ADDR_PLAYBACK_1).
+ // This message is sent as part of the DeviceDiscoveryAction to available devices.
+ HdmiCecMessage givePhysicalAddress = HdmiCecMessageBuilder.buildGivePhysicalAddress(ADDR_TV,
+ ADDR_PLAYBACK_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(givePhysicalAddress);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 29b96ebdc090..668f04785bbc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1423,7 +1423,6 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Test
public void testActivityOnCancelFixedRotationTransform() {
- mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
final DisplayRotation displayRotation = mActivity.mDisplayContent.getDisplayRotation();
spyOn(displayRotation);
@@ -1480,7 +1479,6 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Test
public void testIsSnapshotCompatible() {
- mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
.setRotation(mActivity.getWindowConfiguration().getRotation())
.build();
@@ -1494,7 +1492,6 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Test
public void testFixedRotationSnapshotStartingWindow() {
- mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
// TaskSnapshotSurface requires a fullscreen opaque window.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
@@ -1509,6 +1506,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
.setRotation((mActivity.getWindowConfiguration().getRotation() + 1) % 4)
.build();
setRotatedScreenOrientationSilently(mActivity);
+ mActivity.setVisible(false);
final IWindowSession session = WindowManagerGlobal.getWindowSession();
spyOn(session);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index a16bd2a72a83..1d13788bc523 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -455,8 +455,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testTransferStartingWindowSetFixedRotation() {
- mWm.mIsFixedRotationTransformEnabled = true;
final ActivityRecord topActivity = createTestActivityRecordForGivenTask(mTask);
+ topActivity.setVisible(false);
mTask.positionChildAt(topActivity, POSITION_TOP);
mActivity.addStartingWindow(mPackageName,
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
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 545901e550c1..105af4fce394 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1067,7 +1067,6 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void testApplyTopFixedRotationTransform() {
- mWm.mIsFixedRotationTransformEnabled = true;
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
// Only non-movable (gesture) navigation bar will be animated by fixed rotation animation.
doReturn(false).when(displayPolicy).navigationBarCanMove();
@@ -1082,6 +1081,7 @@ public class DisplayContentTests extends WindowTestsBase {
mDisplayContent.onRequestedOverrideConfigurationChanged(config);
final ActivityRecord app = mAppWindow.mActivityRecord;
+ app.setVisible(false);
mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
false /* alwaysKeepCurrent */);
mDisplayContent.mOpeningApps.add(app);
@@ -1136,8 +1136,7 @@ public class DisplayContentTests extends WindowTestsBase {
// Launch another activity before the transition is finished.
final ActivityRecord app2 = new ActivityTestsBase.StackBuilder(mWm.mRoot)
.setDisplay(mDisplayContent).build().getTopMostActivity();
- mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
- false /* alwaysKeepCurrent */);
+ app2.setVisible(false);
mDisplayContent.mOpeningApps.add(app2);
app2.setRequestedOrientation(newOrientation);
@@ -1164,6 +1163,29 @@ public class DisplayContentTests extends WindowTestsBase {
}
@Test
+ public void testFinishFixedRotationNoAppTransitioningTask() {
+ final ActivityRecord app = mAppWindow.mActivityRecord;
+ final Task task = app.getTask();
+ final ActivityRecord app2 = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+ .setTask(task).build();
+ mDisplayContent.setFixedRotationLaunchingApp(app2, (mDisplayContent.getRotation() + 1) % 4);
+ doReturn(true).when(task).isAppTransitioning();
+ // If the task is animating transition, this should be no-op.
+ mDisplayContent.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(app.token);
+
+ assertTrue(app2.hasFixedRotationTransform());
+ assertTrue(mDisplayContent.hasTopFixedRotationLaunchingApp());
+
+ doReturn(false).when(task).isAppTransitioning();
+ // Although this notifies app instead of app2 that uses the fixed rotation, app2 should
+ // still finish the transform because there is no more transition event.
+ mDisplayContent.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(app.token);
+
+ assertFalse(app2.hasFixedRotationTransform());
+ assertFalse(mDisplayContent.hasTopFixedRotationLaunchingApp());
+ }
+
+ @Test
public void testRotateSeamlesslyWithFixedRotation() {
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
final ActivityRecord app = mAppWindow.mActivityRecord;
@@ -1183,7 +1205,6 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void testNoFixedRotationWithPip() {
- mWm.mIsFixedRotationTransformEnabled = true;
// Make resume-top really update the activity state.
doReturn(false).when(mWm.mAtmService).isBooting();
doReturn(true).when(mWm.mAtmService).isBooted();
@@ -1258,6 +1279,14 @@ public class DisplayContentTests extends WindowTestsBase {
mDisplayContent.setFixedRotationLaunchingAppUnchecked(mAppWindow.mActivityRecord);
displayRotation.setRotation((displayRotation.getRotation() + 1) % 4);
assertTrue(displayRotation.updateRotationUnchecked(false));
+
+ // The recents activity should not apply fixed rotation if the top activity is not opaque.
+ mDisplayContent.mFocusedApp = mAppWindow.mActivityRecord;
+ doReturn(false).when(mDisplayContent.mFocusedApp).occludesParent();
+ doReturn(ROTATION_90).when(mDisplayContent).rotationForActivityInDifferentOrientation(
+ eq(recentsActivity));
+ mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recentsActivity);
+ assertFalse(recentsActivity.hasFixedRotationTransform());
}
@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 976ac2323989..0a27e1a1da68 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -30,7 +30,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -41,7 +40,6 @@ import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
-import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.test.InsetsModeSession;
@@ -188,13 +186,23 @@ public class InsetsStateControllerTest extends WindowTestsBase {
@Test
public void testStripForDispatch_imeOrderChanged() {
- getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
+ // This can be the IME z-order target while app cannot be the IME z-order target.
+ // This is also the only IME control target in this test, so IME won't be invisible caused
+ // by the control-target change.
+ mDisplayContent.mInputMethodInputTarget = createWindow(null, TYPE_APPLICATION, "base");
- // This window can be the IME target while app cannot be the IME target.
- createWindow(null, TYPE_APPLICATION, "base");
+ // Make IME and stay visible during the test.
+ mImeWindow.setHasSurface(true);
+ getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
+ getController().onImeControlTargetChanged(mDisplayContent.mInputMethodInputTarget);
+ final InsetsState requestedState = new InsetsState();
+ requestedState.getSource(ITYPE_IME).setVisible(true);
+ mDisplayContent.mInputMethodInputTarget.updateRequestedInsetsState(requestedState);
+ getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget, requestedState);
// Send our spy window (app) into the system so that we can detect the invocation.
final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
+ win.setHasSurface(true);
final WindowToken parent = win.mToken;
parent.removeChild(win);
final WindowState app = spy(win);
@@ -206,7 +214,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
mDisplayContent.applySurfaceChangesTransaction();
// app won't get visible IME insets while above IME even when IME is visible.
- getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
+ assertTrue(getController().getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
assertFalse(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
// Reset invocation counter.
@@ -220,8 +228,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
// Make sure app got notified.
verify(app, atLeast(1)).notifyInsetsChanged();
- // app will get visible IME insets while below IME when IME is visible.
- getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
+ // app will get visible IME insets while below IME.
assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 243468aba8e8..8e85e7b96d1f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -321,7 +321,6 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Test
public void testRecentViewInFixedPortraitWhenTopAppInLandscape() {
- mWm.mIsFixedRotationTransformEnabled = true;
mWm.setRecentsAnimationController(mController);
final ActivityRecord homeActivity = createHomeActivity();
@@ -390,7 +389,6 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Test
public void testWallpaperHasFixedRotationApplied() {
- mWm.mIsFixedRotationTransformEnabled = true;
mWm.setRecentsAnimationController(mController);
// Create a portrait home activity, a wallpaper and a landscape activity displayed on top.
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index e742b32ff4b8..3c98272311f7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -511,13 +511,13 @@ public class SizeCompatTests extends ActivityTestsBase {
@Test
public void testLaunchWithFixedRotationTransform() {
- mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
final int dw = 1000;
final int dh = 2500;
final int notchHeight = 200;
setUpApp(new TestDisplayContent.Builder(mService, dw, dh).setNotch(notchHeight).build());
addStatusBar(mActivity.mDisplayContent);
+ mActivity.setVisible(false);
mActivity.mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
false /* alwaysKeepCurrent */);
mActivity.mDisplayContent.mOpeningApps.add(mActivity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index 373f363e31ff..53ede60e9ac7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -101,7 +101,6 @@ public class WallpaperControllerTests extends WindowTestsBase {
public void testWallpaperSizeWithFixedTransform() {
// No wallpaper
final DisplayContent dc = createNewDisplay();
- dc.mWmService.mIsFixedRotationTransformEnabled = true;
// No wallpaper WSA Surface
WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
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 7ce0c1edfb4c..341e20946c30 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -729,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));
- finishAndNotifyDrawing(w);
+ w.immediatelyNotifyBlastSync();
assertEquals(true, bse.addToSyncSet(id2, task));
bse.setReady(id2);
}
@@ -753,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());
- finishAndNotifyDrawing(w);
+ w.immediatelyNotifyBlastSync();
verify(transactionListener)
.onTransactionReady(anyInt(), any());
}
@@ -821,14 +821,14 @@ public class WindowOrganizerTests extends WindowTestsBase {
int id = bse.startSyncSet(transactionListener);
assertEquals(true, bse.addToSyncSet(id, task));
bse.setReady(id);
- finishAndNotifyDrawing(w);
+ w.immediatelyNotifyBlastSync();
// Since we have a child window we still shouldn't be done.
verify(transactionListener, never())
.onTransactionReady(anyInt(), any());
reset(transactionListener);
- finishAndNotifyDrawing(child);
+ child.immediatelyNotifyBlastSync();
// Ah finally! Done
verify(transactionListener)
.onTransactionReady(anyInt(), any());
@@ -1002,20 +1002,15 @@ public class WindowOrganizerTests extends WindowTestsBase {
verify(mockCallback, never()).onTransactionReady(anyInt(), any());
assertTrue(w1.useBLASTSync());
assertTrue(w2.useBLASTSync());
- finishAndNotifyDrawing(w1);
+ w1.immediatelyNotifyBlastSync();
// Even though one Window finished drawing, both windows should still be using blast sync
assertTrue(w1.useBLASTSync());
assertTrue(w2.useBLASTSync());
- finishAndNotifyDrawing(w2);
+ w2.immediatelyNotifyBlastSync();
verify(mockCallback).onTransactionReady(anyInt(), any());
assertFalse(w1.useBLASTSync());
assertFalse(w2.useBLASTSync());
}
-
- private void finishAndNotifyDrawing(WindowState ws) {
- ws.finishDrawing(null);
- ws.notifyBlastSyncTransaction();
- }
}
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 1a38a42873b7..bc987a6282c7 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -303,12 +303,6 @@ public final class TelephonyPermissions {
String message, boolean allowCarrierPrivilegeOnAnySub) {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
- PermissionManager permissionManager = (PermissionManager) context.getSystemService(
- Context.PERMISSION_SERVICE);
- if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId,
- pid, uid) == PackageManager.PERMISSION_GRANTED) {
- return true;
- }
// If the calling package has carrier privileges for specified sub, then allow access.
if (checkCarrierPrivilegeForSubId(context, subId)) return true;
@@ -319,6 +313,13 @@ public final class TelephonyPermissions {
return true;
}
+ PermissionManager permissionManager = (PermissionManager) context.getSystemService(
+ Context.PERMISSION_SERVICE);
+ if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId,
+ pid, uid) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+
return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
message);
}
@@ -433,16 +434,6 @@ public final class TelephonyPermissions {
public static boolean checkReadPhoneNumber(
Context context, int subId, int pid, int uid,
String callingPackage, @Nullable String callingFeatureId, String message) {
- // Default SMS app can always read it.
- AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
- if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage, callingFeatureId,
- null) == AppOpsManager.MODE_ALLOWED) {
- return true;
- }
-
- // NOTE(b/73308711): If an app has one of the following AppOps bits explicitly revoked, they
- // will be denied access, even if they have another permission and AppOps bit if needed.
-
// First, check if the SDK version is below R
boolean preR = false;
try {
@@ -477,21 +468,29 @@ public final class TelephonyPermissions {
}
}
+ // Default SMS app can always read it.
+ AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage, callingFeatureId,
+ null) == AppOpsManager.MODE_ALLOWED) {
+ return true;
+ }
// Can be read with READ_SMS too.
try {
context.enforcePermission(android.Manifest.permission.READ_SMS, pid, uid, message);
- return appOps.noteOp(AppOpsManager.OPSTR_READ_SMS, uid, callingPackage,
- callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
-
+ if (appOps.noteOp(AppOpsManager.OPSTR_READ_SMS, uid, callingPackage,
+ callingFeatureId, null) == AppOpsManager.MODE_ALLOWED) {
+ return true;
+ }
} catch (SecurityException readSmsSecurityException) {
}
// Can be read with READ_PHONE_NUMBERS too.
try {
context.enforcePermission(android.Manifest.permission.READ_PHONE_NUMBERS, pid, uid,
message);
- return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, uid, callingPackage,
- callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
-
+ if (appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, uid, callingPackage,
+ callingFeatureId, null) == AppOpsManager.MODE_ALLOWED) {
+ return true;
+ }
} catch (SecurityException readPhoneNumberSecurityException) {
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index d62cd0a63b44..11667c83bc6a 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -305,11 +305,14 @@ public class SubscriptionInfo implements Parcelable {
}
/**
- * Returns the ICC ID if the calling app has been granted the READ_PRIVILEGED_PHONE_STATE
- * permission, has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or
- * is a device owner or profile owner that has been granted the READ_PHONE_STATE permission.
- * The profile owner is an app that owns a managed profile on the device; for more details see
- * <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile
+ * Returns the ICC ID.
+ *
+ * Starting with API level 30, returns the ICC ID if the calling app has been granted the
+ * READ_PRIVILEGED_PHONE_STATE permission, has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}), or is a device owner or profile owner that
+ * has been granted the READ_PHONE_STATE permission. The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile
* owner access is deprecated and will be removed in a future release.
*
* @return the ICC ID, or an empty string if one of these requirements is not met
@@ -449,8 +452,22 @@ public class SubscriptionInfo implements Parcelable {
}
/**
- * @return the number of this subscription if the calling app has been granted the
- * READ_PHONE_NUMBERS permission, or an empty string otherwise
+ * Returns the number of this subscription.
+ *
+ * Starting with API level 30, returns the number of this subscription if the calling app meets
+ * one of the following requirements:
+ * <ul>
+ * <li>If the calling app's target SDK is API level 29 or lower and the app has been granted
+ * the READ_PHONE_STATE permission.
+ * <li>If the calling app has been granted any of READ_PRIVILEGED_PHONE_STATE,
+ * READ_PHONE_NUMBERS, or READ_SMS.
+ * <li>If the calling app has carrier privileges (see {@link
+ * TelephonyManager#hasCarrierPrivileges}).
+ * <li>If the calling app is the default SMS role holder.
+ * </ul>
+ *
+ * @return the number of this subscription, or an empty string if one of these requirements is
+ * not met
*/
public String getNumber() {
return mNumber;
@@ -670,12 +687,15 @@ public class SubscriptionInfo implements Parcelable {
}
/**
- * Returns the card string if the calling app has been granted the READ_PRIVILEGED_PHONE_STATE
- * permission, has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or
- * is a device owner or profile owner on an organization owned device that has been granted the
- * READ_PHONE_STATE permission. The profile owner is an app that owns a managed profile on the
- * device; for more details see <a href="https://developer.android.com/work/managed-profiles">
- * Work profiles</a>.
+ * Returns the card string of the SIM card which contains the subscription.
+ *
+ * Starting with API level 30, returns the card string if the calling app has been granted the
+ * READ_PRIVILEGED_PHONE_STATE permission, has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}), or is a device owner or profile owner that
+ * has been granted the READ_PHONE_STATE permission. The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile
+ * owner access is deprecated and will be removed in a future release.
*
* @return the card string of the SIM card which contains the subscription or an empty string
* if these requirements are not met. The card string is the ICCID for UICCs or the EID for
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ee146089b852..8ae1ee99b060 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -38,6 +38,7 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.app.PendingIntent;
+import android.app.role.RoleManager;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
@@ -1885,12 +1886,23 @@ public class TelephonyManager {
* Returns the unique device ID, for example, the IMEI for GSM and the MEID
* or ESN for CDMA phones. Return null if device ID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner
- * is an app that owns a managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) on any
+ * active subscription.
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -1927,12 +1939,23 @@ public class TelephonyManager {
* Returns the unique device ID of a subscription, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner
- * is an app that owns a managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) on any
+ * active subscription.
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -1985,18 +2008,23 @@ public class TelephonyManager {
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
*
- * <p>This API requires one of the following:
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
* <ul>
- * <li>The caller holds the READ_PRIVILEGED_PHONE_STATE permission.</li>
- * <li>If the caller is the device or profile owner, the caller holds the
- * {@link Manifest.permission#READ_PHONE_STATE} permission.</li>
- * <li>The caller has carrier privileges (see {@link #hasCarrierPrivileges()} on any
- * active subscription.</li>
- * <li>The caller is the default SMS app for the device.</li>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) on any
+ * active subscription.
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
* </ul>
- * <p>The profile owner is an app that owns a managed profile on the device; for more details
- * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
- * Access by profile owners is deprecated and will be removed in a future release.
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -2058,12 +2086,23 @@ public class TelephonyManager {
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner
- * is an app that owns a managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) on any
+ * active subscription.
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -2085,12 +2124,23 @@ public class TelephonyManager {
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner
- * is an app that owns a managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) on any
+ * active subscription.
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -2158,12 +2208,25 @@ public class TelephonyManager {
/**
* Returns the Network Access Identifier (NAI). Return null if NAI is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
- * managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
+ *
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
*
* <ul>
* <li>If the calling app's target SDK is API level 28 or lower and the app has the
@@ -2182,12 +2245,25 @@ public class TelephonyManager {
/**
* Returns the NAI. Return null if NAI is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
- * managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
+ *
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
*
* <ul>
* <li>If the calling app's target SDK is API level 28 or lower and the app has the
@@ -3775,12 +3851,22 @@ public class TelephonyManager {
* Returns the serial number of the SIM, if applicable. Return null if it is
* unavailable.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
- * managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -3803,12 +3889,22 @@ public class TelephonyManager {
* Returns the serial number for the given subscription, if applicable. Return null if it is
* unavailable.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
- * managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -4047,12 +4143,22 @@ public class TelephonyManager {
* Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
* Return null if it is unavailable.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
- * managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
@@ -4076,12 +4182,22 @@ public class TelephonyManager {
* for a subscription.
* Return null if it is unavailable.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
- * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
- * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
- * managed profile on the device; for more details see <a
- * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
- * access is deprecated and will be removed in a future release.
+ * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
+ * restrictions, and apps are recommended to use resettable identifiers (see <a
+ * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
+ * the following requirements is met:
+ * <ul>
+ * <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+ * is a privileged permission that can only be granted to apps preloaded on the device.
+ * <li>If the calling app is the device or profile owner and has been granted the
+ * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
+ * owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Profile owner access is deprecated and will be removed in a future release.
+ * <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <li>If the calling app is the default SMS role holder (see {@link
+ * RoleManager#isRoleHeld(String)}).
+ * </ul>
*
* <p>If the calling app does not meet one of these requirements then this method will behave
* as follows:
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
index 4a0ca664049a..2df0024bdea9 100644
--- a/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
@@ -153,7 +153,14 @@ public class DummyBlobData {
public void writeToSession(BlobStoreManager.Session session,
long offsetBytes, long lengthBytes) throws Exception {
try (FileInputStream in = new FileInputStream(mFile)) {
- Utils.writeToSession(session, in, offsetBytes, lengthBytes);
+ Utils.writeToSession(session, in, offsetBytes, lengthBytes, lengthBytes);
+ }
+ }
+
+ public void writeToSession(BlobStoreManager.Session session,
+ long offsetBytes, long lengthBytes, long allocateBytes) throws Exception {
+ try (FileInputStream in = new FileInputStream(mFile)) {
+ Utils.writeToSession(session, in, offsetBytes, lengthBytes, allocateBytes);
}
}
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
index b9bd661dfd67..ec859955694c 100644
--- a/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
@@ -59,15 +59,15 @@ public class Utils {
public static void writeToSession(BlobStoreManager.Session session, ParcelFileDescriptor input,
long lengthBytes) throws IOException {
try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(input)) {
- writeToSession(session, in, 0, lengthBytes);
+ writeToSession(session, in, 0, lengthBytes, lengthBytes);
}
}
public static void writeToSession(BlobStoreManager.Session session, FileInputStream in,
- long offsetBytes, long lengthBytes) throws IOException {
+ long offsetBytes, long lengthBytes, long allocateBytes) throws IOException {
in.getChannel().position(offsetBytes);
try (FileOutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(
- session.openWrite(offsetBytes, lengthBytes))) {
+ session.openWrite(offsetBytes, allocateBytes))) {
copy(in, out, lengthBytes);
}
}
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
new file mode 100644
index 000000000000..c3fdd695c2b7
--- /dev/null
+++ b/tests/StagedInstallTest/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+ name: "StagedInstallInternalTestApp",
+ manifest: "app/AndroidManifest.xml",
+ srcs: ["app/src/**/*.java"],
+ static_libs: ["androidx.test.rules", "cts-install-lib"],
+ test_suites: ["general-tests"],
+}
+
+java_test_host {
+ name: "StagedInstallInternalTest",
+ srcs: ["src/**/*.java"],
+ libs: ["tradefed"],
+ static_libs: ["testng", "compatibility-tradefed"],
+ test_suites: ["general-tests"],
+ test_config: "StagedInstallInternalTest.xml",
+}
+
diff --git a/tests/StagedInstallTest/StagedInstallInternalTest.xml b/tests/StagedInstallTest/StagedInstallInternalTest.xml
new file mode 100644
index 000000000000..1b8fa672fe38
--- /dev/null
+++ b/tests/StagedInstallTest/StagedInstallInternalTest.xml
@@ -0,0 +1,33 @@
+<?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 the internal staged install tests">
+ <option name="test-suite-tag" value="StagedInstallTest" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="StagedInstallInternalTestApp.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.A" />
+ <option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
+ <option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.A" />
+ <option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="class"
+ value="com.android.tests.stagedinstallinternal.host.StagedInstallInternalTest" />
+ </test>
+</configuration>
diff --git a/tests/StagedInstallTest/TEST_MAPPING b/tests/StagedInstallTest/TEST_MAPPING
new file mode 100644
index 000000000000..5a7a5a766b88
--- /dev/null
+++ b/tests/StagedInstallTest/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "StagedInstallInternalTest"
+ }
+ ]
+}
diff --git a/tests/StagedInstallTest/app/AndroidManifest.xml b/tests/StagedInstallTest/app/AndroidManifest.xml
new file mode 100644
index 000000000000..a678f1ec3691
--- /dev/null
+++ b/tests/StagedInstallTest/app/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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.tests.stagedinstallinternal" >
+
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <application>
+ <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
+ android:exported="true" />
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.tests.stagedinstallinternal"
+ android:label="StagedInstallInternal Test"/>
+
+</manifest>
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
new file mode 100644
index 000000000000..02597d548361
--- /dev/null
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.stagedinstallinternal;
+
+import static com.android.cts.install.lib.InstallUtils.getPackageInstaller;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.Manifest;
+import android.content.pm.PackageInstaller;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.cts.install.lib.Install;
+import com.android.cts.install.lib.InstallUtils;
+import com.android.cts.install.lib.TestApp;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.function.Consumer;
+
+@RunWith(JUnit4.class)
+public class StagedInstallInternalTest {
+
+ private static final String TAG = StagedInstallInternalTest.class.getSimpleName();
+
+ private File mTestStateFile = new File(
+ InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
+ "stagedinstall_state");
+
+ /**
+ * Adopts common shell permissions needed for staged install tests.
+ */
+ @Before
+ public void adoptShellPermissions() {
+ InstallUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES
+ );
+ }
+
+ /**
+ * Drops shell permissions needed for staged install tests.
+ */
+ @After
+ public void dropShellPermissions() {
+ InstallUtils.dropShellPermissionIdentity();
+ }
+
+ // This is marked as @Test to take advantage of @Before/@After methods of this class. Actual
+ // purpose of this method to be called before and after each test case of
+ // com.android.test.stagedinstall.host.StagedInstallTest to reduce tests flakiness.
+ @Test
+ public void cleanUp() throws Exception {
+ Files.deleteIfExists(mTestStateFile.toPath());
+ }
+
+ @Test
+ public void testSystemServerRestartDoesNotAffectStagedSessions_Commit() throws Exception {
+ int sessionId = Install.single(TestApp.A1).setStaged().commit();
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
+ assertSessionReady(sessionId);
+ storeSessionId(sessionId);
+ }
+
+ @Test
+ public void testSystemServerRestartDoesNotAffectStagedSessions_Verify() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
+ int sessionId = retrieveLastSessionId();
+ assertSessionReady(sessionId);
+ }
+
+ private static void assertSessionReady(int sessionId) {
+ assertSessionState(sessionId,
+ (session) -> assertThat(session.isStagedSessionReady()).isTrue());
+ }
+
+ private static void assertSessionState(
+ int sessionId, Consumer<PackageInstaller.SessionInfo> assertion) {
+ PackageInstaller packageInstaller = getPackageInstaller();
+
+ List<PackageInstaller.SessionInfo> sessions = packageInstaller.getStagedSessions();
+ boolean found = false;
+ for (PackageInstaller.SessionInfo session : sessions) {
+ if (session.getSessionId() == sessionId) {
+ assertion.accept(session);
+ found = true;
+ }
+ }
+ assertWithMessage("Expecting to find session in getStagedSession()")
+ .that(found).isTrue();
+
+ // Test also that getSessionInfo correctly returns the session.
+ PackageInstaller.SessionInfo sessionInfo = packageInstaller.getSessionInfo(sessionId);
+ assertion.accept(sessionInfo);
+ }
+
+ private void storeSessionId(int sessionId) throws Exception {
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(mTestStateFile))) {
+ writer.write("" + sessionId);
+ }
+ }
+
+ private int retrieveLastSessionId() throws Exception {
+ try (BufferedReader reader = new BufferedReader(new FileReader(mTestStateFile))) {
+ return Integer.parseInt(reader.readLine());
+ }
+ }
+}
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
new file mode 100644
index 000000000000..9b432f7d0ca5
--- /dev/null
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.stagedinstallinternal.host;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.ddmlib.Log;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.ProcessInfo;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class StagedInstallInternalTest extends BaseHostJUnit4Test {
+
+ private static final String TAG = StagedInstallInternalTest.class.getSimpleName();
+ private static final long SYSTEM_SERVER_TIMEOUT_MS = 60 * 1000;
+ private boolean mWasRoot = false;
+
+ /**
+ * Runs the given phase of a test by calling into the device.
+ * Throws an exception if the test phase fails.
+ * <p>
+ * For example, <code>runPhase("testApkOnlyEnableRollback");</code>
+ */
+ private void runPhase(String phase) throws Exception {
+ assertTrue(runDeviceTests("com.android.tests.stagedinstallinternal",
+ "com.android.tests.stagedinstallinternal.StagedInstallInternalTest",
+ phase));
+ }
+
+ // We do not assert the success of cleanup phase since it might fail due to flaky reasons.
+ private void cleanUp() throws Exception {
+ try {
+ runDeviceTests("com.android.tests.stagedinstallinternal",
+ "com.android.tests.stagedinstallinternal.StagedInstallInternalTest",
+ "cleanUp");
+ } catch (AssertionError e) {
+ Log.e(TAG, e);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mWasRoot = getDevice().isAdbRoot();
+ if (!mWasRoot) {
+ getDevice().enableAdbRoot();
+ }
+ cleanUp();
+ // Abandon all staged sessions
+ getDevice().executeShellCommand("pm install-abandon $(pm get-stagedsessions --only-ready "
+ + "--only-parent --only-sessionid)");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (!mWasRoot) {
+ getDevice().disableAdbRoot();
+ }
+ cleanUp();
+ }
+
+ @Test
+ public void testSystemServerRestartDoesNotAffectStagedSessions() throws Exception {
+ runPhase("testSystemServerRestartDoesNotAffectStagedSessions_Commit");
+ restartSystemServer();
+ runPhase("testSystemServerRestartDoesNotAffectStagedSessions_Verify");
+ }
+
+ private void restartSystemServer() throws Exception {
+ // Restart the system server
+ long oldStartTime = getDevice().getProcessByName("system_server").getStartTime();
+ assertThat(getDevice().executeShellCommand("am restart")).contains("Restart the system");
+
+ // Wait for new system server process to start
+ long start = System.currentTimeMillis();
+ long newStartTime = oldStartTime;
+ while (System.currentTimeMillis() < start + SYSTEM_SERVER_TIMEOUT_MS) {
+ ProcessInfo newPs = getDevice().getProcessByName("system_server");
+ if (newPs != null) {
+ newStartTime = newPs.getStartTime();
+ if (newStartTime != oldStartTime) {
+ break;
+ }
+ }
+ Thread.sleep(500);
+ }
+ assertThat(newStartTime).isNotEqualTo(oldStartTime);
+ getDevice().waitForDeviceAvailable();
+ }
+}
diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
index 0a603b8e4b19..508b5cd9cb19 100644
--- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
@@ -62,6 +62,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.test.FakeSettingsProvider;
+import libcore.net.InetAddressUtils;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -103,7 +105,8 @@ public class DnsManagerTest {
@NonNull ResolverOptionsParcel expected) {
assertEquals(actual.hosts, expected.hosts);
assertEquals(actual.tcMode, expected.tcMode);
- assertFieldCountEquals(2, ResolverOptionsParcel.class);
+ assertEquals(actual.enforceDnsUid, expected.enforceDnsUid);
+ assertFieldCountEquals(3, ResolverOptionsParcel.class);
}
private void assertResolverParamsEquals(@NonNull ResolverParamsParcel actual,
@@ -379,4 +382,49 @@ public class DnsManagerTest {
assertEquals(name, dnsTransTypes.get(i));
}
}
+
+ @Test
+ public void testGetPrivateDnsConfigForNetwork() throws Exception {
+ final Network network = new Network(TEST_NETID);
+ final InetAddress dnsAddr = InetAddressUtils.parseNumericAddress("3.3.3.3");
+ final InetAddress[] tlsAddrs = new InetAddress[]{
+ InetAddressUtils.parseNumericAddress("6.6.6.6"),
+ InetAddressUtils.parseNumericAddress("2001:db8:66:66::1")
+ };
+ final String tlsName = "strictmode.com";
+ LinkProperties lp = new LinkProperties();
+ lp.addDnsServer(dnsAddr);
+
+ // The PrivateDnsConfig map is empty, so the default PRIVATE_DNS_OFF is returned.
+ PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
+ assertFalse(privateDnsCfg.useTls);
+ assertEquals("", privateDnsCfg.hostname);
+ assertEquals(new InetAddress[0], privateDnsCfg.ips);
+
+ // An entry with default PrivateDnsConfig is added to the PrivateDnsConfig map.
+ mDnsManager.updatePrivateDns(network, mDnsManager.getPrivateDnsConfig());
+ mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, dnsAddr, "", true));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
+ assertTrue(privateDnsCfg.useTls);
+ assertEquals("", privateDnsCfg.hostname);
+ assertEquals(new InetAddress[0], privateDnsCfg.ips);
+
+ // The original entry is overwritten by a new PrivateDnsConfig.
+ mDnsManager.updatePrivateDns(network, new PrivateDnsConfig(tlsName, tlsAddrs));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
+ assertTrue(privateDnsCfg.useTls);
+ assertEquals(tlsName, privateDnsCfg.hostname);
+ assertEquals(tlsAddrs, privateDnsCfg.ips);
+
+ // The network is removed, so the PrivateDnsConfig map becomes empty again.
+ mDnsManager.removeNetwork(network);
+ privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
+ assertFalse(privateDnsCfg.useTls);
+ assertEquals("", privateDnsCfg.hostname);
+ assertEquals(new InetAddress[0], privateDnsCfg.ips);
+ }
}
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index b1e2487c54fe..e3b6db08c503 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -21,7 +21,6 @@ cc_binary_host {
name: "stats-log-api-gen",
srcs: [
"Collation.cpp",
- "atoms_info_writer.cpp",
"java_writer.cpp",
"java_writer_q.cpp",
"main.cpp",
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 958e94efcf9c..a230de46dcf3 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -52,9 +52,7 @@ AtomDecl::AtomDecl(const AtomDecl& that)
defaultState(that.defaultState),
triggerStateReset(that.triggerStateReset),
nested(that.nested),
- uidField(that.uidField),
- whitelisted(that.whitelisted),
- truncateTimestamp(that.truncateTimestamp) {
+ uidField(that.uidField) {
}
AtomDecl::AtomDecl(int c, const string& n, const string& m) : code(c), name(n), message(m) {
@@ -520,13 +518,6 @@ int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms*
shared_ptr<AtomDecl> atomDecl =
make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
- if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) {
- atomDecl->whitelisted = true;
- if (dbg) {
- printf("%s is whitelisted\n", atomField->name().c_str());
- }
- }
-
if (atomDecl->code < PULL_ATOM_START_ID &&
atomField->options().GetExtension(os::statsd::truncate_timestamp)) {
addAnnotationToAtomDecl(atomDecl.get(), ATOM_ID_FIELD_NUMBER,
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index 043f8b1e74d8..10b34ecf5f54 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -164,10 +164,6 @@ struct AtomDecl {
int uidField = 0;
- bool whitelisted = false;
-
- bool truncateTimestamp = false;
-
AtomDecl();
AtomDecl(const AtomDecl& that);
AtomDecl(int code, const string& name, const string& message);
diff --git a/tools/stats_log_api_gen/atoms_info_writer.cpp b/tools/stats_log_api_gen/atoms_info_writer.cpp
deleted file mode 100644
index 292cb21bac30..000000000000
--- a/tools/stats_log_api_gen/atoms_info_writer.cpp
+++ /dev/null
@@ -1,91 +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.
- */
-
-#include "atoms_info_writer.h"
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-static void write_atoms_info_header_body(FILE* out) {
- fprintf(out, "struct AtomsInfo {\n");
- fprintf(out, " const static std::set<int> kWhitelistedAtoms;\n");
- fprintf(out, "};\n");
-}
-
-static void write_atoms_info_cpp_body(FILE* out, const Atoms& atoms) {
-
- fprintf(out, "const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n");
- for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
- atomIt++) {
- if ((*atomIt)->whitelisted) {
- const string constant = make_constant_name((*atomIt)->name);
- fprintf(out, " %d, // %s\n", (*atomIt)->code, constant.c_str());
- }
- }
-
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
-}
-
-int write_atoms_info_header(FILE* out, const string& namespaceStr) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "#pragma once\n");
- fprintf(out, "\n");
- fprintf(out, "#include <vector>\n");
- fprintf(out, "#include <map>\n");
- fprintf(out, "#include <set>\n");
- fprintf(out, "\n");
-
- write_namespace(out, namespaceStr);
-
- write_atoms_info_header_body(out);
-
- fprintf(out, "\n");
- write_closing_namespace(out, namespaceStr);
-
- return 0;
-}
-
-int write_atoms_info_cpp(FILE* out, const Atoms& atoms, const string& namespaceStr,
- const string& importHeader) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "#include <%s>\n", importHeader.c_str());
- fprintf(out, "\n");
-
- write_namespace(out, namespaceStr);
-
- write_atoms_info_cpp_body(out, atoms);
-
- // Print footer
- fprintf(out, "\n");
- write_closing_namespace(out, namespaceStr);
-
- return 0;
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/atoms_info_writer.h b/tools/stats_log_api_gen/atoms_info_writer.h
deleted file mode 100644
index 09a4303eaee6..000000000000
--- a/tools/stats_log_api_gen/atoms_info_writer.h
+++ /dev/null
@@ -1,35 +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.
- */
-
-#pragma once
-
-#include <stdio.h>
-#include <string.h>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using namespace std;
-
-int write_atoms_info_cpp(FILE* out, const Atoms& atoms, const string& namespaceStr,
- const string& importHeader);
-
-int write_atoms_info_header(FILE* out, const string& namespaceStr);
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 136933b8cfb2..b888ce904b31 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -9,7 +9,6 @@
#include <vector>
#include "Collation.h"
-#include "atoms_info_writer.h"
#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
#include "java_writer.h"
#include "java_writer_q.h"
@@ -30,12 +29,6 @@ static void print_usage() {
fprintf(stderr, "OPTIONS\n");
fprintf(stderr, " --cpp FILENAME the header file to output for write helpers\n");
fprintf(stderr, " --header FILENAME the cpp file to output for write helpers\n");
- fprintf(stderr,
- " --atomsInfoCpp FILENAME the header file to output for "
- "statsd metadata\n");
- fprintf(stderr,
- " --atomsInfoHeader FILENAME the cpp file to output for statsd "
- "metadata\n");
fprintf(stderr, " --help this message\n");
fprintf(stderr, " --java FILENAME the java file to output\n");
fprintf(stderr, " --module NAME optional, module name to generate outputs for\n");
@@ -49,10 +42,6 @@ static void print_usage() {
" --importHeader NAME required for cpp/jni to say which header to "
"import "
"for write helpers\n");
- fprintf(stderr,
- " --atomsInfoImportHeader NAME required for cpp to say which "
- "header to import "
- "for statsd metadata\n");
fprintf(stderr, " --javaPackage PACKAGE the package for the java file.\n");
fprintf(stderr, " required for java with module\n");
fprintf(stderr, " --javaClass CLASS the class name of the java class.\n");
@@ -74,15 +63,12 @@ static int run(int argc, char const* const* argv) {
string cppFilename;
string headerFilename;
string javaFilename;
- string atomsInfoCppFilename;
- string atomsInfoHeaderFilename;
string javaPackage;
string javaClass;
string moduleName = DEFAULT_MODULE_NAME;
string cppNamespace = DEFAULT_CPP_NAMESPACE;
string cppHeaderImport = DEFAULT_CPP_HEADER_IMPORT;
- string atomsInfoCppHeaderImport = DEFAULT_ATOMS_INFO_CPP_HEADER_IMPORT;
bool supportQ = false;
bool supportWorkSource = false;
bool compileQ = false;
@@ -148,27 +134,6 @@ static int run(int argc, char const* const* argv) {
return 1;
}
javaClass = argv[index];
- } else if (0 == strcmp("--atomsInfoHeader", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- atomsInfoHeaderFilename = argv[index];
- } else if (0 == strcmp("--atomsInfoCpp", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- atomsInfoCppFilename = argv[index];
- } else if (0 == strcmp("--atomsInfoImportHeader", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- atomsInfoCppHeaderImport = argv[index];
} else if (0 == strcmp("--supportQ", argv[index])) {
supportQ = true;
} else if (0 == strcmp("--worksource", argv[index])) {
@@ -180,8 +145,7 @@ static int run(int argc, char const* const* argv) {
index++;
}
- if (cppFilename.size() == 0 && headerFilename.size() == 0 && javaFilename.size() == 0 &&
- atomsInfoHeaderFilename.size() == 0 && atomsInfoCppFilename.size() == 0) {
+ if (cppFilename.size() == 0 && headerFilename.size() == 0 && javaFilename.size() == 0) {
print_usage();
return 1;
}
@@ -210,29 +174,6 @@ static int run(int argc, char const* const* argv) {
collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl,
&attributionSignature);
- // Write the atoms info .cpp file
- if (atomsInfoCppFilename.size() != 0) {
- FILE* out = fopen(atomsInfoCppFilename.c_str(), "w");
- if (out == NULL) {
- fprintf(stderr, "Unable to open file for write: %s\n", atomsInfoCppFilename.c_str());
- return 1;
- }
- errorCount = android::stats_log_api_gen::write_atoms_info_cpp(out, atoms, cppNamespace,
- atomsInfoCppHeaderImport);
- fclose(out);
- }
-
- // Write the atoms info .h file
- if (atomsInfoHeaderFilename.size() != 0) {
- FILE* out = fopen(atomsInfoHeaderFilename.c_str(), "w");
- if (out == NULL) {
- fprintf(stderr, "Unable to open file for write: %s\n", atomsInfoHeaderFilename.c_str());
- return 1;
- }
- errorCount = android::stats_log_api_gen::write_atoms_info_header(out, cppNamespace);
- fclose(out);
- }
-
// Write the .cpp file
if (cppFilename.size() != 0) {
FILE* out = fopen(cppFilename.c_str(), "w");
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index d22acc6e6598..aaa488e44fee 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -187,24 +187,6 @@ message GoodStateAtom3 {
optional int32 state = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
}
-message WhitelistedAtom {
- optional int32 field = 1;
-}
-
-message NonWhitelistedAtom {
- optional int32 field = 1;
-}
-
-message ListedAtoms {
- oneof event {
- // Atoms can be whitelisted i.e. they can be triggered by any source
- WhitelistedAtom whitelisted_atom = 1 [(android.os.statsd.allow_from_any_uid) = true];
- // Atoms are not whitelisted by default, so they can only be triggered
- // by whitelisted sources
- NonWhitelistedAtom non_whitelisted_atom = 2;
- }
-}
-
message ModuleOneAtom {
optional int32 field = 1 [(android.os.statsd.is_uid) = true];
}
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
index 150475223bfa..dbae58889333 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -225,25 +225,6 @@ TEST(CollationTest, FailOnBadBinaryFieldAtom) {
EXPECT_TRUE(errorCount > 0);
}
-TEST(CollationTest, PassOnWhitelistedAtom) {
- Atoms atoms;
- int errorCount = collate_atoms(ListedAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- EXPECT_EQ(errorCount, 0);
- EXPECT_EQ(atoms.decls.size(), 2ul);
-}
-
-TEST(CollationTest, RecogniseWhitelistedAtom) {
- Atoms atoms;
- collate_atoms(ListedAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- for (const auto& atomDecl : atoms.decls) {
- if (atomDecl->code == 1) {
- EXPECT_TRUE(atomDecl->whitelisted);
- } else {
- EXPECT_FALSE(atomDecl->whitelisted);
- }
- }
-}
-
TEST(CollationTest, PassOnLogFromModuleAtom) {
Atoms atoms;
int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index 7d6d08ebbcbe..73e0cb838227 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -32,7 +32,6 @@ using namespace std;
const string DEFAULT_CPP_NAMESPACE = "android,util";
const string DEFAULT_CPP_HEADER_IMPORT = "statslog.h";
-const string DEFAULT_ATOMS_INFO_CPP_HEADER_IMPORT = "atoms_info.h";
const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 2bcd4f4241a6..a5e76e6c92ee 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -885,7 +885,8 @@ public final class SoftApConfiguration implements Parcelable {
/**
* Configure the Soft AP to require manual user control of client association.
- * If disabled (the default) then any client can associate to this Soft AP using the
+ * If disabled (the default) then any client which isn't in the blocked list
+ * {@link #getBlockedClientList()} can associate to this Soft AP using the
* correct credentials until the Soft AP capacity is reached (capacity is hardware, carrier,
* or user limited - using {@link #setMaxNumberOfClients(int)}).
*
@@ -945,21 +946,19 @@ public final class SoftApConfiguration implements Parcelable {
}
/**
- * This method together with {@link setClientControlByUserEnabled(boolean)} control client
- * connections to the AP. If client control by user is disabled using the above method then
- * this API has no effect and clients are allowed to associate to the AP (within limit of
- * max number of clients).
+ * This API configures the list of clients which are blocked and cannot associate
+ * to the Soft AP.
*
- * If client control by user is enabled then this API this API configures the list of
- * clients which are blocked. These are rejected.
+ * <p>
+ * This method requires hardware support. Hardware support can be determined using
+ * {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
+ * {@link SoftApCapability#areFeaturesSupported(int)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT}
*
- * All other clients which attempt to associate, whose MAC addresses are on neither list,
- * are:
- * <ul>
- * <li>Rejected</li>
- * <li>A callback {@link WifiManager.SoftApCallback#onBlockedClientConnecting(WifiClient)}
- * is issued (which allows the user to add them to the allowed client list if desired).<li>
- * </ul>
+ * <p>
+ * If the method is called on a device without hardware support then starting the soft AP
+ * using {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will fail with
+ * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
*
* @param blockedClientList list of clients which are not allowed to associate to the AP.
* @return Builder for chaining.
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index d35ce3c7a42c..77fa673f1960 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -93,6 +93,8 @@ public class WifiEnterpriseConfig implements Parcelable {
public static final String OPP_KEY_CACHING = "proactive_key_caching";
/** @hide */
public static final String EAP_ERP = "eap_erp";
+ /** @hide */
+ public static final String OCSP = "ocsp";
/**
* String representing the keystore OpenSSL ENGINE's ID.
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 1b0497a0ecd5..fb6af5b550b0 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -928,19 +928,26 @@ public class WifiManager {
/**
* Broadcast intent action indicating that the configured networks changed.
- * This can be as a result of adding/updating/deleting a network. If
- * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration
- * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple
- * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present.
+ * This can be as a result of adding/updating/deleting a network.
+ * <br />
+ * {@link #EXTRA_CHANGE_REASON} contains whether the configuration was added/changed/removed.
+ * {@link #EXTRA_WIFI_CONFIGURATION} is never set starting in Android 11.
+ * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set for backwards compatibility reasons, but
+ * its value is always true, even if only a single network changed.
+ * <br />
+ * The {@link android.Manifest.permission#ACCESS_WIFI_STATE ACCESS_WIFI_STATE} permission is
+ * required to receive this broadcast.
+ *
* @hide
*/
@SystemApi
public static final String CONFIGURED_NETWORKS_CHANGED_ACTION =
"android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
/**
- * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing
+ * The lookup key for a {@link android.net.wifi.WifiConfiguration} object representing
* the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION}
* broadcast is sent.
+ * Note: this extra is never set starting in Android 11.
* @hide
*/
@SystemApi
@@ -948,14 +955,16 @@ public class WifiManager {
/**
* Multiple network configurations have changed.
* @see #CONFIGURED_NETWORKS_CHANGED_ACTION
- *
+ * Note: this extra is always true starting in Android 11.
* @hide
*/
@SystemApi
public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
/**
* The lookup key for an integer indicating the reason a Wi-Fi network configuration
- * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false}
+ * has changed. One of {@link #CHANGE_REASON_ADDED}, {@link #CHANGE_REASON_REMOVED},
+ * {@link #CHANGE_REASON_CONFIG_CHANGE}.
+ *
* @see #CONFIGURED_NETWORKS_CHANGED_ACTION
* @hide
*/