summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--api/current.txt73
-rw-r--r--api/system-current.txt74
-rw-r--r--api/test-current.txt74
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java59
-rw-r--r--cmds/sm/src/com/android/commands/sm/Sm.java12
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java12
-rw-r--r--core/java/android/accessibilityservice/GestureDescription.java3
-rw-r--r--core/java/android/app/ActivityManagerNative.java2
-rw-r--r--core/java/android/app/ActivityThread.java17
-rw-r--r--core/java/android/app/BackStackRecord.java4
-rw-r--r--core/java/android/app/Fragment.java3
-rw-r--r--core/java/android/app/Notification.java147
-rw-r--r--core/java/android/app/NotificationManager.java14
-rw-r--r--core/java/android/app/UiAutomationConnection.java7
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java92
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl5
-rw-r--r--core/java/android/app/backup/BackupAgent.java40
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java34
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java3
-rw-r--r--core/java/android/content/ContentResolver.java75
-rw-r--r--core/java/android/content/IContentService.aidl2
-rw-r--r--core/java/android/content/Intent.java25
-rw-r--r--core/java/android/content/IntentFilter.java22
-rw-r--r--core/java/android/content/pm/PackageParser.java32
-rw-r--r--core/java/android/content/res/Resources.java11
-rw-r--r--core/java/android/ddm/DdmHandleHello.java5
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java17
-rw-r--r--core/java/android/hardware/camera2/CaptureResult.java3
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java1
-rw-r--r--core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java7
-rw-r--r--core/java/android/hardware/camera2/legacy/CameraDeviceState.java18
-rw-r--r--core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java10
-rw-r--r--core/java/android/hardware/camera2/legacy/CaptureCollector.java40
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java55
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestHolder.java18
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestThreadManager.java3
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java3
-rw-r--r--core/java/android/hardware/input/InputManager.java2
-rw-r--r--core/java/android/hardware/input/InputManagerInternal.java7
-rw-r--r--core/java/android/hardware/location/ContextHubInfo.java18
-rw-r--r--core/java/android/hardware/location/ContextHubService.java70
-rw-r--r--core/java/android/hardware/location/MemoryRegion.java27
-rw-r--r--core/java/android/hardware/location/NanoApp.java10
-rw-r--r--core/java/android/hardware/location/NanoAppInstanceInfo.java11
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java59
-rw-r--r--core/java/android/net/ConnectivityManager.java1
-rw-r--r--core/java/android/net/ConnectivityMetricsEvent.aidl1
-rw-r--r--core/java/android/net/ConnectivityMetricsEvent.java38
-rw-r--r--core/java/android/net/ConnectivityMetricsLogger.java70
-rw-r--r--core/java/android/net/DnsPinger.java334
-rw-r--r--core/java/android/net/IConnectivityMetricsLogger.aidl23
-rw-r--r--core/java/android/net/NetworkScorerAppManager.java37
-rw-r--r--core/java/android/os/BatteryStats.java36
-rw-r--r--core/java/android/os/Handler.java14
-rw-r--r--core/java/android/os/INetworkManagementService.aidl5
-rw-r--r--core/java/android/os/Looper.java20
-rw-r--r--core/java/android/os/PowerManager.java12
-rw-r--r--core/java/android/os/storage/StorageManager.java18
-rw-r--r--core/java/android/preference/Preference.java17
-rw-r--r--core/java/android/preference/PreferenceGroup.java20
-rw-r--r--core/java/android/preference/PreferenceManager.java9
-rwxr-xr-xcore/java/android/provider/Settings.java20
-rw-r--r--core/java/android/service/vr/IVrManager.aidl46
-rw-r--r--core/java/android/service/vr/IVrStateCallbacks.aidl (renamed from core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl)15
-rw-r--r--core/java/android/text/BoringLayout.java4
-rw-r--r--core/java/android/text/StaticLayout.java14
-rw-r--r--core/java/android/view/ContextThemeWrapper.java9
-rw-r--r--core/java/android/view/KeyEvent.java5
-rw-r--r--core/java/android/view/NotificationHeaderView.java26
-rw-r--r--core/java/android/view/RenderNode.java22
-rw-r--r--core/java/android/view/ScaleGestureDetector.java88
-rw-r--r--core/java/android/view/View.java52
-rw-r--r--core/java/android/view/ViewRootImpl.java9
-rw-r--r--core/java/android/view/WindowInfo.java12
-rw-r--r--core/java/android/view/WindowManager.java17
-rw-r--r--core/java/android/view/WindowManagerPolicy.java5
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java10
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java57
-rw-r--r--core/java/android/view/accessibility/AccessibilityWindowInfo.java62
-rw-r--r--core/java/android/view/animation/Animation.java10
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java10
-rw-r--r--core/java/android/webkit/WebViewDelegate.java20
-rw-r--r--core/java/android/webkit/WebViewFactory.java13
-rw-r--r--core/java/android/widget/AccessibilityIterators.java17
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java2
-rw-r--r--core/java/android/widget/CalendarView.java4
-rw-r--r--core/java/android/widget/CalendarViewLegacyDelegate.java2
-rw-r--r--core/java/android/widget/DatePicker.java15
-rw-r--r--core/java/android/widget/DayPickerPagerAdapter.java5
-rw-r--r--core/java/android/widget/EditText.java3
-rw-r--r--core/java/android/widget/Editor.java70
-rw-r--r--core/java/android/widget/ListView.java4
-rw-r--r--core/java/android/widget/PopupWindow.java218
-rw-r--r--core/java/android/widget/TextView.java111
-rw-r--r--core/java/android/widget/Toolbar.java10
-rw-r--r--core/java/com/android/internal/app/procstats/SparseMappingTable.java20
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetService.aidl4
-rw-r--r--core/java/com/android/internal/os/BackgroundThread.java2
-rw-r--r--core/java/com/android/internal/os/PowerProfile.java9
-rw-r--r--core/java/com/android/internal/policy/IKeyguardService.aidl7
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java6
-rw-r--r--core/java/com/android/internal/util/FastXmlSerializer.java21
-rw-r--r--core/java/com/android/internal/widget/FloatingToolbar.java1
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl3
-rw-r--r--core/java/com/android/internal/widget/LockPatternChecker.java37
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java57
-rw-r--r--core/java/com/android/internal/widget/ResolverDrawerLayout.java52
-rw-r--r--core/java/com/android/server/net/NetlinkTracker.java13
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/android/graphics/AvoidXfermode.cpp177
-rw-r--r--core/jni/android/graphics/AvoidXfermode.h70
-rw-r--r--core/jni/android/graphics/Paint.cpp37
-rw-r--r--core/jni/android/graphics/SurfaceTexture.cpp4
-rw-r--r--core/jni/android_graphics_drawable_VectorDrawable.cpp209
-rw-r--r--core/jni/android_hardware_location_ContextHubService.cpp44
-rw-r--r--core/res/AndroidManifest.xml17
-rw-r--r--core/res/res/anim/slide_in_enter_micro.xml2
-rw-r--r--core/res/res/layout/notification_material_action_list.xml4
-rw-r--r--core/res/res/layout/notification_template_header.xml23
-rw-r--r--core/res/res/layout/notification_template_material_big_base.xml6
-rw-r--r--core/res/res/layout/notification_template_material_big_picture.xml9
-rw-r--r--core/res/res/layout/notification_template_material_big_text.xml61
-rw-r--r--core/res/res/layout/notification_template_material_inbox.xml170
-rw-r--r--core/res/res/layout/resolver_list.xml122
-rw-r--r--core/res/res/layout/resolver_list_with_default.xml164
-rw-r--r--core/res/res/values-af/strings.xml13
-rw-r--r--core/res/res/values-am/strings.xml13
-rw-r--r--core/res/res/values-ar/strings.xml13
-rw-r--r--core/res/res/values-az-rAZ/strings.xml13
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml13
-rw-r--r--core/res/res/values-be-rBY/strings.xml17
-rw-r--r--core/res/res/values-bg/strings.xml13
-rw-r--r--core/res/res/values-bn-rBD/strings.xml13
-rw-r--r--core/res/res/values-bs-rBA/strings.xml13
-rw-r--r--core/res/res/values-ca/strings.xml15
-rw-r--r--core/res/res/values-cs/strings.xml13
-rw-r--r--core/res/res/values-da/strings.xml13
-rw-r--r--core/res/res/values-de/strings.xml13
-rw-r--r--core/res/res/values-el/strings.xml13
-rw-r--r--core/res/res/values-en-rAU/strings.xml13
-rw-r--r--core/res/res/values-en-rGB/strings.xml13
-rw-r--r--core/res/res/values-en-rIN/strings.xml13
-rw-r--r--core/res/res/values-es-rUS/strings.xml13
-rw-r--r--core/res/res/values-es/strings.xml13
-rw-r--r--core/res/res/values-et-rEE/strings.xml13
-rw-r--r--core/res/res/values-eu-rES/strings.xml13
-rw-r--r--core/res/res/values-fa/strings.xml13
-rw-r--r--core/res/res/values-fi/strings.xml13
-rw-r--r--core/res/res/values-fr-rCA/strings.xml13
-rw-r--r--core/res/res/values-fr/strings.xml13
-rw-r--r--core/res/res/values-gl-rES/strings.xml13
-rw-r--r--core/res/res/values-gu-rIN/strings.xml13
-rw-r--r--core/res/res/values-hi/strings.xml13
-rw-r--r--core/res/res/values-hr/strings.xml13
-rw-r--r--core/res/res/values-hu/strings.xml13
-rw-r--r--core/res/res/values-hy-rAM/strings.xml13
-rw-r--r--core/res/res/values-in/strings.xml17
-rw-r--r--core/res/res/values-is-rIS/strings.xml13
-rw-r--r--core/res/res/values-it/strings.xml13
-rw-r--r--core/res/res/values-iw/strings.xml13
-rw-r--r--core/res/res/values-ja/strings.xml13
-rw-r--r--core/res/res/values-ka-rGE/strings.xml13
-rw-r--r--core/res/res/values-kk-rKZ/strings.xml13
-rw-r--r--core/res/res/values-km-rKH/strings.xml13
-rw-r--r--core/res/res/values-kn-rIN/strings.xml13
-rw-r--r--core/res/res/values-ko/strings.xml13
-rw-r--r--core/res/res/values-ky-rKG/strings.xml13
-rw-r--r--core/res/res/values-lo-rLA/strings.xml13
-rw-r--r--core/res/res/values-lt/strings.xml13
-rw-r--r--core/res/res/values-lv/strings.xml13
-rw-r--r--core/res/res/values-mk-rMK/strings.xml13
-rw-r--r--core/res/res/values-ml-rIN/strings.xml13
-rw-r--r--core/res/res/values-mn-rMN/strings.xml13
-rw-r--r--core/res/res/values-mr-rIN/strings.xml13
-rw-r--r--core/res/res/values-ms-rMY/strings.xml13
-rw-r--r--core/res/res/values-my-rMM/strings.xml13
-rw-r--r--core/res/res/values-nb/strings.xml13
-rw-r--r--core/res/res/values-ne-rNP/strings.xml13
-rw-r--r--core/res/res/values-nl/strings.xml13
-rw-r--r--core/res/res/values-pa-rIN/strings.xml13
-rw-r--r--core/res/res/values-pl/strings.xml13
-rw-r--r--core/res/res/values-pt-rBR/strings.xml13
-rw-r--r--core/res/res/values-pt-rPT/strings.xml13
-rw-r--r--core/res/res/values-pt/strings.xml13
-rw-r--r--core/res/res/values-ro/strings.xml13
-rw-r--r--core/res/res/values-ru/strings.xml13
-rw-r--r--core/res/res/values-si-rLK/strings.xml13
-rw-r--r--core/res/res/values-sk/strings.xml13
-rw-r--r--core/res/res/values-sl/strings.xml13
-rw-r--r--core/res/res/values-sq-rAL/strings.xml13
-rw-r--r--core/res/res/values-sr/strings.xml13
-rw-r--r--core/res/res/values-sv/strings.xml13
-rw-r--r--core/res/res/values-sw/strings.xml13
-rw-r--r--core/res/res/values-ta-rIN/strings.xml13
-rw-r--r--core/res/res/values-te-rIN/strings.xml13
-rw-r--r--core/res/res/values-th/strings.xml13
-rw-r--r--core/res/res/values-tl/strings.xml13
-rw-r--r--core/res/res/values-tr/strings.xml13
-rw-r--r--core/res/res/values-uk/strings.xml13
-rw-r--r--core/res/res/values-ur-rPK/strings.xml13
-rw-r--r--core/res/res/values-uz-rUZ/strings.xml13
-rw-r--r--core/res/res/values-vi/strings.xml13
-rw-r--r--core/res/res/values-zh-rCN/strings.xml15
-rw-r--r--core/res/res/values-zh-rHK/strings.xml13
-rw-r--r--core/res/res/values-zh-rTW/strings.xml13
-rw-r--r--core/res/res/values-zu/strings.xml13
-rw-r--r--core/res/res/values/config.xml16
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/symbols.xml9
-rw-r--r--core/res/res/xml/power_profile.xml26
-rw-r--r--core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java82
-rw-r--r--core/tests/coretests/src/android/print/IPrintManagerParametersTest.java2
-rw-r--r--core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java414
-rw-r--r--core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java25
-rw-r--r--core/tests/coretests/src/android/widget/TextViewActivityTest.java32
-rw-r--r--core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java25
-rw-r--r--core/tests/coretests/src/android/widget/espresso/MouseClickAction.java19
-rw-r--r--core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java121
-rw-r--r--core/tests/coretests/src/android/widget/espresso/TextViewActions.java11
-rw-r--r--core/tests/coretests/src/android/widget/espresso/ViewClickAction.java61
-rw-r--r--core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java105
-rw-r--r--data/fonts/Android.mk2
-rw-r--r--graphics/java/android/graphics/Outline.java20
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java3
-rw-r--r--libs/hwui/BakedOpDispatcher.cpp4
-rw-r--r--libs/hwui/BakedOpRenderer.cpp4
-rw-r--r--libs/hwui/BakedOpRenderer.h1
-rw-r--r--libs/hwui/DisplayList.cpp1
-rw-r--r--libs/hwui/DisplayList.h16
-rw-r--r--libs/hwui/DisplayListCanvas.cpp3
-rw-r--r--libs/hwui/DisplayListOp.h8
-rw-r--r--libs/hwui/FrameBuilder.cpp5
-rw-r--r--libs/hwui/FrameBuilder.h6
-rw-r--r--libs/hwui/PropertyValuesHolder.cpp10
-rw-r--r--libs/hwui/RecordedOp.h11
-rw-r--r--libs/hwui/RecordingCanvas.cpp3
-rw-r--r--libs/hwui/RenderNode.cpp3
-rw-r--r--libs/hwui/RenderProperties.cpp17
-rw-r--r--libs/hwui/SkiaCanvas.cpp6
-rw-r--r--libs/hwui/VectorDrawable.cpp503
-rw-r--r--libs/hwui/VectorDrawable.h770
-rw-r--r--libs/hwui/renderstate/OffscreenBufferPool.cpp2
-rw-r--r--libs/hwui/tests/unit/FrameBuilderTests.cpp47
-rw-r--r--libs/hwui/tests/unit/LeakCheckTests.cpp19
-rw-r--r--libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp197
-rw-r--r--media/java/android/media/DrmInitData.java6
-rw-r--r--media/java/android/media/MediaActionSound.java141
-rw-r--r--media/java/android/media/MediaExtractor.java25
-rw-r--r--media/java/android/media/browse/MediaBrowser.java2
-rw-r--r--media/java/android/media/browse/MediaBrowserUtils.java4
-rw-r--r--media/java/android/media/midi/IMidiDeviceServer.aidl3
-rw-r--r--media/java/android/media/midi/MidiDevice.java14
-rw-r--r--media/java/android/media/midi/MidiDeviceServer.java3
-rw-r--r--media/java/android/service/media/MediaBrowserService.java4
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp12
-rw-r--r--packages/CtsShim/Android.mk61
-rw-r--r--packages/CtsShim/priv_shim/AndroidManifest.xml157
-rw-r--r--packages/CtsShim/shim/AndroidManifest.xml47
-rw-r--r--packages/DocumentsUI/AndroidManifest.xml18
-rw-r--r--packages/DocumentsUI/app-perf-tests/AndroidManifest.xml2
-rw-r--r--packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java9
-rw-r--r--packages/DocumentsUI/res/drawable/drag_shadow_background.xml28
-rw-r--r--packages/DocumentsUI/res/layout/drag_shadow_layout.xml44
-rw-r--r--packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_downloads.png (renamed from packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png)bin4473 -> 4473 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_downloads.png (renamed from packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png)bin2818 -> 2818 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_downloads.png (renamed from packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png)bin6351 -> 6351 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_downloads.png (renamed from packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png)bin10361 -> 10361 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_downloads.png (renamed from packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png)bin14962 -> 14962 bytes
-rw-r--r--packages/DocumentsUI/res/values-af/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-am/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ar/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-az-rAZ/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-b+sr+Latn/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-be-rBY/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-bg/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-bn-rBD/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-bs-rBA/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ca/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-cs/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-da/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-de/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-el/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-en-rAU/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-en-rGB/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-en-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-es-rUS/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-es/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-et-rEE/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-eu-rES/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-fa/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-fi/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-fr-rCA/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-fr/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-gl-rES/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-gu-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-hi/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-hr/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-hu/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-hy-rAM/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-in/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-is-rIS/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-it/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-iw/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ja/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ka-rGE/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-kk-rKZ/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-km-rKH/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-kn-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ko/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ky-rKG/strings.xml5
-rw-r--r--packages/DocumentsUI/res/values-lo-rLA/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-lt/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-lv/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-mk-rMK/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ml-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-mn-rMN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-mr-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ms-rMY/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-my-rMM/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-nb/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ne-rNP/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-nl/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-pa-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-pl/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-pt-rBR/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-pt-rPT/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-pt/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ro/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ru/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-si-rLK/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-sk/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-sl/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-sq-rAL/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-sr/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-sv/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-sw/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ta-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-te-rIN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-th/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-tl/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-tr/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-uk/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-ur-rPK/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-uz-rUZ/strings.xml3
-rw-r--r--packages/DocumentsUI/res/values-vi/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-zh-rCN/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-zh-rHK/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-zh-rTW/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values-zu/strings.xml1
-rw-r--r--packages/DocumentsUI/res/values/colors.xml1
-rw-r--r--packages/DocumentsUI/res/values/config.xml14
-rw-r--r--packages/DocumentsUI/res/values/dimens.xml4
-rw-r--r--packages/DocumentsUI/res/values/strings.xml9
-rw-r--r--packages/DocumentsUI/res/values/styles.xml1
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java33
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/Display.java37
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DrawerController.java2
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java11
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java19
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/Metrics.java41
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsCache.java37
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java5
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/Shared.java49
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/State.java5
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java114
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java4
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java9
-rw-r--r--packages/Keyguard/res/drawable/ic_backspace_24dp.xml1
-rw-r--r--packages/Keyguard/res/values/attrs.xml3
-rw-r--r--packages/Keyguard/src/com/android/keyguard/NumPadKey.java12
-rw-r--r--packages/Keyguard/src/com/android/keyguard/PasswordTextView.java27
-rw-r--r--packages/PrintServiceRecommendationService/res/values/strings.xml2
-rw-r--r--packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml4
-rw-r--r--packages/PrintSpooler/res/layout/print_activity_controls.xml3
-rw-r--r--packages/PrintSpooler/res/values-af/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-am/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ar/strings.xml8
-rw-r--r--packages/PrintSpooler/res/values-az-rAZ/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-b+sr+Latn/strings.xml5
-rw-r--r--packages/PrintSpooler/res/values-be-rBY/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-bg/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-bn-rBD/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-bs-rBA/strings.xml5
-rw-r--r--packages/PrintSpooler/res/values-ca/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-cs/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-da/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-de/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-el/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-en-rAU/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-en-rGB/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-en-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-es-rUS/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-es/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-et-rEE/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-eu-rES/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-fa/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-fi/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-fr-rCA/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-fr/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-gl-rES/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-gu-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-hi/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-hr/strings.xml5
-rw-r--r--packages/PrintSpooler/res/values-hu/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-hy-rAM/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-in/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-is-rIS/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-it/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-iw/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-ja/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ka-rGE/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-kk-rKZ/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-km-rKH/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-kn-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ko/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ky-rKG/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-lo-rLA/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-lt/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-lv/strings.xml5
-rw-r--r--packages/PrintSpooler/res/values-mk-rMK/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ml-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-mn-rMN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-mr-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ms-rMY/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-my-rMM/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-nb/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ne-rNP/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-nl/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-pa-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-pl/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-pt-rBR/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-pt-rPT/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-pt/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ro/strings.xml5
-rw-r--r--packages/PrintSpooler/res/values-ru/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-si-rLK/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-sk/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-sl/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-sq-rAL/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-sr/strings.xml5
-rw-r--r--packages/PrintSpooler/res/values-sv/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-sw/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-ta-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-te-rIN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-th/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-tl/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-tr/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-uk/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-ur-rPK/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-uz-rUZ/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-vi/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-zh-rCN/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-zh-rHK/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-zh-rTW/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-zu/strings.xml4
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java100
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java39
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java163
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-az-rAZ/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-be-rBY/strings.xml20
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-bn-rBD/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-bs-rBA/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml11
-rw-r--r--packages/SettingsLib/res/values-et-rEE/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-eu-rES/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-gl-rES/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-gu-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-hy-rAM/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-is-rIS/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ka-rGE/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-kk-rKZ/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-km-rKH/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-kn-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ky-rKG/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-lo-rLA/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-mk-rMK/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ml-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-mn-rMN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-mr-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ms-rMY/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-my-rMM/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ne-rNP/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-pa-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-si-rLK/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-sq-rAL/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ta-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-te-rIN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-ur-rPK/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-uz-rUZ/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml18
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml18
-rw-r--r--packages/SettingsLib/res/values/strings.xml25
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java38
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java68
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java18
-rwxr-xr-xpackages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java4
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java3
-rw-r--r--packages/SystemUI/AndroidManifest.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml27
-rw-r--r--packages/SystemUI/res/drawable/ic_ksh_key_down.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_ksh_key_enter.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_ksh_key_left.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_ksh_key_meta.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_ksh_key_right.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_ksh_key_up.xml25
-rw-r--r--packages/SystemUI/res/drawable/tv_pip_close_button.xml16
-rw-r--r--packages/SystemUI/res/drawable/tv_pip_full_button.xml16
-rw-r--r--packages/SystemUI/res/drawable/tv_pip_pause_button.xml16
-rw-r--r--packages/SystemUI/res/drawable/tv_pip_play_button.xml16
-rw-r--r--packages/SystemUI/res/layout/battery_detail.xml10
-rw-r--r--packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml (renamed from packages/SystemUI/res/values-h560dp/config.xml)15
-rw-r--r--packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml10
-rw-r--r--packages/SystemUI/res/layout/qs_customize_tile_divider.xml (renamed from core/res/res/layout/notification_action_list.xml)19
-rw-r--r--packages/SystemUI/res/layout/qs_detail.xml8
-rw-r--r--packages/SystemUI/res/layout/qs_detail_items.xml17
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request_buttons.xml15
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml15
-rw-r--r--packages/SystemUI/res/values-af/strings.xml14
-rw-r--r--packages/SystemUI/res/values-am/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml14
-rw-r--r--packages/SystemUI/res/values-az-rAZ/strings.xml14
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml14
-rw-r--r--packages/SystemUI/res/values-be-rBY/strings.xml20
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml14
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings.xml14
-rw-r--r--packages/SystemUI/res/values-bs-rBA/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml28
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml14
-rw-r--r--packages/SystemUI/res/values-da/strings.xml14
-rw-r--r--packages/SystemUI/res/values-de/strings.xml14
-rw-r--r--packages/SystemUI/res/values-el/strings.xml14
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml14
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml14
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml16
-rw-r--r--packages/SystemUI/res/values-es/strings.xml14
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml14
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings.xml14
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml14
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml14
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml14
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml14
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings.xml14
-rw-r--r--packages/SystemUI/res/values-gu-rIN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml14
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml14
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml14
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml14
-rw-r--r--packages/SystemUI/res/values-in/strings.xml14
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings.xml14
-rw-r--r--packages/SystemUI/res/values-it/strings.xml16
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings.xml14
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings.xml14
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings.xml14
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings.xml16
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml10
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml14
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml16
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml14
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-mr-rIN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml14
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings.xml14
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml18
-rw-r--r--packages/SystemUI/res/values-ne-rNP/strings.xml16
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml14
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml14
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml14
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml14
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml20
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings.xml14
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml14
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml14
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings.xml14
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml14
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml14
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml14
-rw-r--r--packages/SystemUI/res/values-sw410dp/config.xml24
-rw-r--r--packages/SystemUI/res/values-sw410dp/dimens.xml24
-rw-r--r--packages/SystemUI/res/values-sw540dp/config.xml24
-rw-r--r--packages/SystemUI/res/values-sw600dp-land/dimens.xml4
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings.xml14
-rw-r--r--packages/SystemUI/res/values-te-rIN/strings.xml18
-rw-r--r--packages/SystemUI/res/values-th/strings.xml14
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml14
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml14
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings.xml16
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings.xml16
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml14
-rw-r--r--packages/SystemUI/res/values-w550dp-land/dimens.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml32
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml14
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml14
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml14
-rw-r--r--packages/SystemUI/res/values/attrs.xml4
-rw-r--r--packages/SystemUI/res/values/colors.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml12
-rw-r--r--packages/SystemUI/res/values/dimens.xml6
-rw-r--r--packages/SystemUI/res/values/dimens_tv.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/ResizingSpace.java104
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java121
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainer.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java144
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/TileLayout.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java158
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/FocusAnimationHolder.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java78
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java142
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java318
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java125
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java215
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java4
-rw-r--r--rs/java/android/renderscript/RenderScript.java8
-rw-r--r--rs/java/android/renderscript/RenderScriptGL.java4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java19
-rw-r--r--services/accessibility/java/com/android/server/accessibility/MagnificationController.java5
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java95
-rw-r--r--services/core/java/com/android/server/AnyMotionDetector.java87
-rw-r--r--services/core/java/com/android/server/AppOpsService.java25
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java72
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java38
-rw-r--r--services/core/java/com/android/server/DisplayThread.java2
-rw-r--r--services/core/java/com/android/server/FgThread.java2
-rw-r--r--services/core/java/com/android/server/GestureLauncherService.java5
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java66
-rw-r--r--services/core/java/com/android/server/IoThread.java2
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java428
-rw-r--r--services/core/java/com/android/server/LockSettingsStorage.java95
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java10
-rw-r--r--services/core/java/com/android/server/NetworkScoreService.java137
-rw-r--r--services/core/java/com/android/server/UiThread.java2
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java36
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java34
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java23
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java16
-rw-r--r--services/core/java/com/android/server/am/UserController.java28
-rw-r--r--services/core/java/com/android/server/connectivity/MetricsLoggerService.java334
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java5
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java7
-rw-r--r--services/core/java/com/android/server/content/ContentService.java125
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java16
-rw-r--r--services/core/java/com/android/server/content/SyncStorageEngine.java29
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java24
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java8
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiLogger.java7
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java6
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java23
-rw-r--r--services/core/java/com/android/server/job/controllers/AppIdleController.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/BatteryController.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/ConnectivityController.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/ContentObserverController.java46
-rw-r--r--services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/IdleController.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/StateController.java3
-rw-r--r--services/core/java/com/android/server/job/controllers/TimeController.java4
-rw-r--r--services/core/java/com/android/server/lights/LightsService.java17
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java10
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java57
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java470
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java13
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java19
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java12
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java136
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java4
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java4
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java20
-rw-r--r--services/core/java/com/android/server/trust/TrustAgentWrapper.java2
-rw-r--r--services/core/java/com/android/server/vr/VrManagerInternal.java23
-rw-r--r--services/core/java/com/android/server/vr/VrManagerService.java117
-rw-r--r--services/core/java/com/android/server/webkit/SystemImpl.java (renamed from services/core/java/com/android/server/webkit/WebViewUtilityImpl.java)88
-rw-r--r--services/core/java/com/android/server/webkit/SystemInterface.java (renamed from services/core/java/com/android/server/webkit/WebViewUtilityInterface.java)20
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateService.java805
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java20
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java9
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java20
-rw-r--r--services/core/java/com/android/server/wm/DimLayerController.java7
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java32
-rw-r--r--services/core/java/com/android/server/wm/Task.java6
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowLayersController.java19
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java87
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java202
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java3
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java164
-rw-r--r--services/java/com/android/server/SystemServer.java13
-rw-r--r--services/net/java/android/net/apf/ApfFilter.java122
-rw-r--r--services/net/java/android/net/ip/IpManager.java51
-rw-r--r--services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java378
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java41
-rw-r--r--services/usb/java/com/android/server/usb/UsbMidiDevice.java8
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java19
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl6
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java62
-rw-r--r--telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl3
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneConstants.java6
-rw-r--r--tools/aapt/Package.cpp2
-rw-r--r--tools/aapt2/Android.mk4
-rw-r--r--tools/aapt2/Diagnostics.h93
-rw-r--r--tools/aapt2/ResourceTable_test.cpp42
-rw-r--r--tools/aapt2/java/JavaClassGenerator.cpp18
-rw-r--r--tools/aapt2/java/JavaClassGenerator.h5
-rw-r--r--tools/aapt2/link/Link.cpp11
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp308
-rw-r--r--tools/aapt2/link/ManifestFixer.h11
-rw-r--r--tools/aapt2/link/ManifestFixer_test.cpp12
-rw-r--r--tools/aapt2/test/Builders.h2
-rw-r--r--tools/aapt2/test/Common.h21
-rw-r--r--tools/aapt2/xml/XmlActionExecutor.cpp112
-rw-r--r--tools/aapt2/xml/XmlActionExecutor.h108
-rw-r--r--tools/aapt2/xml/XmlActionExecutor_test.cpp62
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java23
-rw-r--r--tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java17
-rw-r--r--tools/layoutlib/bridge/src/android/view/RectShadowPainter.java8
-rw-r--r--tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java10
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java181
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java6
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java60
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.pngbin10663 -> 10819 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.pngbin7214 -> 7305 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml8
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml8
-rw-r--r--tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java42
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl3
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java25
845 files changed, 15351 insertions, 6361 deletions
diff --git a/Android.mk b/Android.mk
index 1469c2cdf93e..ae5d67ed2de3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -197,7 +197,6 @@ LOCAL_SRC_FILES += \
core/java/android/net/ICaptivePortal.aidl \
core/java/android/net/IConnectivityManager.aidl \
core/java/android/net/IConnectivityMetricsLogger.aidl \
- core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl \
core/java/android/net/IEthernetManager.aidl \
core/java/android/net/IEthernetServiceListener.aidl \
core/java/android/net/INetworkManagementEventObserver.aidl \
@@ -245,6 +244,8 @@ LOCAL_SRC_FILES += \
core/java/android/service/notification/IConditionListener.aidl \
core/java/android/service/notification/IConditionProvider.aidl \
core/java/android/service/vr/IVrListener.aidl \
+ core/java/android/service/vr/IVrManager.aidl \
+ core/java/android/service/vr/IVrStateCallbacks.aidl \
core/java/android/print/ILayoutResultCallback.aidl \
core/java/android/print/IPrinterDiscoveryObserver.aidl \
core/java/android/print/IPrintDocumentAdapter.aidl \
diff --git a/api/current.txt b/api/current.txt
index 07a4f6d117d9..f346e0b6f054 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2485,6 +2485,7 @@ package android {
field public static final int Widget_Material_CompoundButton_CheckBox = 16974435; // 0x1030263
field public static final int Widget_Material_CompoundButton_RadioButton = 16974436; // 0x1030264
field public static final int Widget_Material_CompoundButton_Star = 16974437; // 0x1030265
+ field public static final int Widget_Material_CompoundButton_Switch = 16974554; // 0x10302da
field public static final int Widget_Material_DatePicker = 16974438; // 0x1030266
field public static final int Widget_Material_DropDownItem = 16974439; // 0x1030267
field public static final int Widget_Material_DropDownItem_Spinner = 16974440; // 0x1030268
@@ -2519,6 +2520,7 @@ package android {
field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974500; // 0x10302a4
field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974501; // 0x10302a5
field public static final int Widget_Material_Light_CompoundButton_Star = 16974502; // 0x10302a6
+ field public static final int Widget_Material_Light_CompoundButton_Switch = 16974555; // 0x10302db
field public static final int Widget_Material_Light_DatePicker = 16974503; // 0x10302a7
field public static final int Widget_Material_Light_DropDownItem = 16974504; // 0x10302a8
field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974505; // 0x10302a9
@@ -4977,7 +4979,7 @@ package android.app {
field public int ledARGB;
field public int ledOffMS;
field public int ledOnMS;
- field public int number;
+ field public deprecated int number;
field public int priority;
field public android.app.Notification publicVersion;
field public android.net.Uri sound;
@@ -5024,11 +5026,13 @@ package android.app {
method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
method public java.lang.CharSequence getCancelLabel();
method public java.lang.CharSequence getConfirmLabel();
+ method public boolean getHintContentIntentLaunchesActivity();
method public java.lang.CharSequence getInProgressLabel();
method public boolean isAvailableOffline();
method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+ method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5070,7 +5074,7 @@ package android.app {
method public android.app.Notification.Builder setChronometerCountsDown(boolean);
method public android.app.Notification.Builder setColor(int);
method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
- method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
+ method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
@@ -5087,7 +5091,7 @@ package android.app {
method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
method public android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
- method public android.app.Notification.Builder setNumber(int);
+ method public deprecated android.app.Notification.Builder setNumber(int);
method public android.app.Notification.Builder setOngoing(boolean);
method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
method public android.app.Notification.Builder setPriority(int);
@@ -5205,6 +5209,7 @@ package android.app {
method public android.app.PendingIntent getDisplayIntent();
method public int getGravity();
method public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
method public boolean getHintHideIcon();
method public int getHintScreenTimeout();
method public boolean getHintShowBackgroundOnly();
@@ -5220,6 +5225,7 @@ package android.app {
method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
method public android.app.Notification.WearableExtender setGravity(int);
method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -5919,7 +5925,7 @@ package android.app.admin {
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
- method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
+ method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -7883,6 +7889,7 @@ package android.content {
method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+ method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -7913,6 +7920,8 @@ package android.content {
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+ field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
+ field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8521,8 +8530,9 @@ package android.content {
field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
- field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABLE = "android.intent.action.MANAGED_PROFILE_AVAILABLE";
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
@@ -20070,7 +20080,6 @@ package android.media {
}
public abstract class DrmInitData {
- ctor public DrmInitData();
method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
}
@@ -20325,8 +20334,8 @@ package android.media {
public class MediaActionSound {
ctor public MediaActionSound();
- method public synchronized void load(int);
- method public synchronized void play(int);
+ method public void load(int);
+ method public void play(int);
method public void release();
field public static final int FOCUS_COMPLETE = 1; // 0x1
field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -23449,6 +23458,7 @@ package android.net {
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static deprecated boolean isNetworkTypeValid(int);
+ method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
method public void releaseNetworkRequest(android.app.PendingIntent);
@@ -29074,6 +29084,7 @@ package android.os {
method public boolean isInteractive();
method public boolean isPowerSaveMode();
method public deprecated boolean isScreenOn();
+ method public boolean isSustainedPerformanceModeSupported();
method public boolean isWakeLockLevelSupported(int);
method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
method public void reboot(java.lang.String);
@@ -29700,7 +29711,6 @@ package android.preference {
method protected void onClick();
method protected android.view.View onCreateView(android.view.ViewGroup);
method public void onDependencyChanged(android.preference.Preference, boolean);
- method protected void onDetachedFromActivity();
method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
method public void onParentChanged(android.preference.Preference, boolean);
method protected void onPrepareForRemoval();
@@ -36618,7 +36628,6 @@ package android.telecom {
method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
method public boolean isInCall();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -37307,7 +37316,8 @@ package android.telephony {
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getGroupIdLevel1(int);
- method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
method public java.lang.String getLine1Number(int);
@@ -37376,6 +37386,13 @@ package android.telephony {
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+ field public static final int APPTYPE_CSIM = 4; // 0x4
+ field public static final int APPTYPE_ISIM = 5; // 0x5
+ field public static final int APPTYPE_RUIM = 3; // 0x3
+ field public static final int APPTYPE_SIM = 1; // 0x1
+ field public static final int APPTYPE_USIM = 2; // 0x2
+ field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+ field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -42273,6 +42290,7 @@ package android.view {
method public boolean dispatchDragEvent(android.view.DragEvent);
method protected void dispatchDraw(android.graphics.Canvas);
method public void dispatchDrawableHotspotChanged(float, float);
+ method public void dispatchFinishTemporaryDetach();
method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
@@ -42292,6 +42310,7 @@ package android.view {
method protected void dispatchSetActivated(boolean);
method protected void dispatchSetPressed(boolean);
method protected void dispatchSetSelected(boolean);
+ method public void dispatchStartTemporaryDetach();
method public void dispatchSystemUiVisibilityChanged(int);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
@@ -42504,6 +42523,7 @@ package android.view {
method public boolean isSelected();
method public boolean isShown();
method public boolean isSoundEffectsEnabled();
+ method public final boolean isTemporarilyDetached();
method public boolean isTextAlignmentResolved();
method public boolean isTextDirectionResolved();
method public boolean isVerticalFadingEdgeEnabled();
@@ -44088,8 +44108,6 @@ package android.view.accessibility {
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -44260,6 +44278,7 @@ package android.view.accessibility {
public final class AccessibilityWindowInfo implements android.os.Parcelable {
method public int describeContents();
+ method public android.view.accessibility.AccessibilityNodeInfo getAnchor();
method public void getBoundsInScreen(android.graphics.Rect);
method public android.view.accessibility.AccessibilityWindowInfo getChild(int);
method public int getChildCount();
@@ -44267,6 +44286,7 @@ package android.view.accessibility {
method public int getLayer();
method public android.view.accessibility.AccessibilityWindowInfo getParent();
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
+ method public java.lang.CharSequence getTitle();
method public int getType();
method public boolean isAccessibilityFocused();
method public boolean isActive();
@@ -46258,7 +46278,7 @@ package android.widget {
method public long getMinDate();
method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
method public deprecated int getSelectedWeekBackgroundColor();
- method public boolean getShowWeekNumber();
+ method public deprecated boolean getShowWeekNumber();
method public deprecated int getShownWeekCount();
method public deprecated int getUnfocusedMonthDateColor();
method public int getWeekDayTextAppearance();
@@ -46275,7 +46295,7 @@ package android.widget {
method public deprecated void setSelectedDateVerticalBar(int);
method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
method public deprecated void setSelectedWeekBackgroundColor(int);
- method public void setShowWeekNumber(boolean);
+ method public deprecated void setShowWeekNumber(boolean);
method public deprecated void setShownWeekCount(int);
method public deprecated void setUnfocusedMonthDateColor(int);
method public void setWeekDayTextAppearance(int);
@@ -46422,21 +46442,21 @@ package android.widget {
ctor public DatePicker(android.content.Context, android.util.AttributeSet);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
- method public android.widget.CalendarView getCalendarView();
- method public boolean getCalendarViewShown();
+ method public deprecated android.widget.CalendarView getCalendarView();
+ method public deprecated boolean getCalendarViewShown();
method public int getDayOfMonth();
method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
- method public boolean getSpinnersShown();
+ method public deprecated boolean getSpinnersShown();
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
- method public void setCalendarViewShown(boolean);
+ method public deprecated void setCalendarViewShown(boolean);
method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
- method public void setSpinnersShown(boolean);
+ method public deprecated void setSpinnersShown(boolean);
method public void updateDate(int, int, int);
}
@@ -50008,6 +50028,7 @@ package java.lang {
method public static int compare(boolean, boolean);
method public int compareTo(java.lang.Boolean);
method public static boolean getBoolean(java.lang.String);
+ method public static int hashCode(boolean);
method public static boolean parseBoolean(java.lang.String);
method public static java.lang.String toString(boolean);
method public static java.lang.Boolean valueOf(boolean);
@@ -50025,6 +50046,7 @@ package java.lang {
method public static java.lang.Byte decode(java.lang.String) throws java.lang.NumberFormatException;
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(byte);
method public int intValue();
method public long longValue();
method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50033,6 +50055,7 @@ package java.lang {
method public static java.lang.Byte valueOf(byte);
method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Byte valueOf(java.lang.String) throws java.lang.NumberFormatException;
+ field public static final int BYTES = 1; // 0x1
field public static final byte MAX_VALUE = 127; // 0x7f
field public static final byte MIN_VALUE = -128; // 0xffffff80
field public static final int SIZE = 8; // 0x8
@@ -50070,6 +50093,7 @@ package java.lang {
method public static int getNumericValue(int);
method public static int getType(char);
method public static int getType(int);
+ method public static int hashCode(char);
method public static char highSurrogate(int);
method public static boolean isAlphabetic(int);
method public static boolean isBmpCodePoint(int);
@@ -50130,6 +50154,7 @@ package java.lang {
method public static char toUpperCase(char);
method public static int toUpperCase(int);
method public static java.lang.Character valueOf(char);
+ field public static final int BYTES = 2; // 0x2
field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
field public static final byte CONNECTOR_PUNCTUATION = 23; // 0x17
field public static final byte CONTROL = 15; // 0xf
@@ -50756,6 +50781,7 @@ package java.lang {
method public static int floatToIntBits(float);
method public static int floatToRawIntBits(float);
method public float floatValue();
+ method public static int hashCode(float);
method public static float intBitsToFloat(int);
method public int intValue();
method public static boolean isFinite(float);
@@ -50764,11 +50790,15 @@ package java.lang {
method public static boolean isNaN(float);
method public boolean isNaN();
method public long longValue();
+ method public static float max(float, float);
+ method public static float min(float, float);
method public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+ method public static float sum(float, float);
method public static java.lang.String toHexString(float);
method public static java.lang.String toString(float);
method public static java.lang.Float valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Float valueOf(float);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_EXPONENT = 127; // 0x7f
field public static final float MAX_VALUE = 3.4028235E38f;
field public static final int MIN_EXPONENT = -126; // 0xffffff82
@@ -50948,6 +50978,7 @@ package java.lang {
method public static java.lang.Long valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Long valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Long valueOf(long);
+ field public static final int BYTES = 8; // 0x8
field public static final long MAX_VALUE = 9223372036854775807L; // 0x7fffffffffffffffL
field public static final long MIN_VALUE = -9223372036854775808L; // 0x8000000000000000L
field public static final int SIZE = 64; // 0x40
@@ -51251,6 +51282,7 @@ package java.lang {
method public static java.lang.Short decode(java.lang.String) throws java.lang.NumberFormatException;
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(short);
method public int intValue();
method public long longValue();
method public static short parseShort(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -51260,6 +51292,7 @@ package java.lang {
method public static java.lang.Short valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Short valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Short valueOf(short);
+ field public static final int BYTES = 2; // 0x2
field public static final short MAX_VALUE = 32767; // 0x7fff
field public static final short MIN_VALUE = -32768; // 0xffff8000
field public static final int SIZE = 16; // 0x10
diff --git a/api/system-current.txt b/api/system-current.txt
index fe562bb9014f..e73287ea82f0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2588,6 +2588,7 @@ package android {
field public static final int Widget_Material_CompoundButton_CheckBox = 16974435; // 0x1030263
field public static final int Widget_Material_CompoundButton_RadioButton = 16974436; // 0x1030264
field public static final int Widget_Material_CompoundButton_Star = 16974437; // 0x1030265
+ field public static final int Widget_Material_CompoundButton_Switch = 16974554; // 0x10302da
field public static final int Widget_Material_DatePicker = 16974438; // 0x1030266
field public static final int Widget_Material_DropDownItem = 16974439; // 0x1030267
field public static final int Widget_Material_DropDownItem_Spinner = 16974440; // 0x1030268
@@ -2622,6 +2623,7 @@ package android {
field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974500; // 0x10302a4
field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974501; // 0x10302a5
field public static final int Widget_Material_Light_CompoundButton_Star = 16974502; // 0x10302a6
+ field public static final int Widget_Material_Light_CompoundButton_Switch = 16974555; // 0x10302db
field public static final int Widget_Material_Light_DatePicker = 16974503; // 0x10302a7
field public static final int Widget_Material_Light_DropDownItem = 16974504; // 0x10302a8
field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974505; // 0x10302a9
@@ -5110,7 +5112,7 @@ package android.app {
field public int ledARGB;
field public int ledOffMS;
field public int ledOnMS;
- field public int number;
+ field public deprecated int number;
field public int priority;
field public android.app.Notification publicVersion;
field public android.net.Uri sound;
@@ -5157,11 +5159,13 @@ package android.app {
method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
method public java.lang.CharSequence getCancelLabel();
method public java.lang.CharSequence getConfirmLabel();
+ method public boolean getHintContentIntentLaunchesActivity();
method public java.lang.CharSequence getInProgressLabel();
method public boolean isAvailableOffline();
method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+ method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5203,7 +5207,7 @@ package android.app {
method public android.app.Notification.Builder setChronometerCountsDown(boolean);
method public android.app.Notification.Builder setColor(int);
method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
- method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
+ method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
@@ -5220,7 +5224,7 @@ package android.app {
method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
method public android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
- method public android.app.Notification.Builder setNumber(int);
+ method public deprecated android.app.Notification.Builder setNumber(int);
method public android.app.Notification.Builder setOngoing(boolean);
method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
method public android.app.Notification.Builder setPriority(int);
@@ -5338,6 +5342,7 @@ package android.app {
method public android.app.PendingIntent getDisplayIntent();
method public int getGravity();
method public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
method public boolean getHintHideIcon();
method public int getHintScreenTimeout();
method public boolean getHintShowBackgroundOnly();
@@ -5353,6 +5358,7 @@ package android.app {
method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
method public android.app.Notification.WearableExtender setGravity(int);
method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -6068,7 +6074,7 @@ package android.app.admin {
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException;
- method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
+ method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -8181,6 +8187,7 @@ package android.content {
method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+ method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -8211,6 +8218,8 @@ package android.content {
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+ field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
+ field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8837,8 +8846,9 @@ package android.content {
field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
- field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABLE = "android.intent.action.MANAGED_PROFILE_AVAILABLE";
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
@@ -21549,7 +21559,6 @@ package android.media {
}
public abstract class DrmInitData {
- ctor public DrmInitData();
method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
}
@@ -21804,8 +21813,8 @@ package android.media {
public class MediaActionSound {
ctor public MediaActionSound();
- method public synchronized void load(int);
- method public synchronized void play(int);
+ method public void load(int);
+ method public void play(int);
method public void release();
field public static final int FOCUS_COMPLETE = 1; // 0x1
field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -25185,6 +25194,7 @@ package android.net {
method public boolean isDefaultNetworkActive();
method public static deprecated boolean isNetworkTypeValid(int);
method public boolean isTetheringSupported();
+ method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
method public void releaseNetworkRequest(android.app.PendingIntent);
@@ -31307,6 +31317,7 @@ package android.os {
method public boolean isPowerSaveMode();
method public boolean isScreenBrightnessBoosted();
method public deprecated boolean isScreenOn();
+ method public boolean isSustainedPerformanceModeSupported();
method public boolean isWakeLockLevelSupported(int);
method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
method public void reboot(java.lang.String);
@@ -32004,7 +32015,6 @@ package android.preference {
method protected void onClick();
method protected android.view.View onCreateView(android.view.ViewGroup);
method public void onDependencyChanged(android.preference.Preference, boolean);
- method protected void onDetachedFromActivity();
method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
method public void onParentChanged(android.preference.Preference, boolean);
method protected void onPrepareForRemoval();
@@ -39287,7 +39297,6 @@ package android.telecom {
method public boolean isRinging();
method public boolean isTtySupported();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -40002,7 +40011,8 @@ package android.telephony {
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getGroupIdLevel1(int);
- method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
method public java.lang.String getLine1Number(int);
@@ -40092,6 +40102,13 @@ package android.telephony {
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
+ field public static final int APPTYPE_CSIM = 4; // 0x4
+ field public static final int APPTYPE_ISIM = 5; // 0x5
+ field public static final int APPTYPE_RUIM = 3; // 0x3
+ field public static final int APPTYPE_SIM = 1; // 0x1
+ field public static final int APPTYPE_USIM = 2; // 0x2
+ field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+ field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -45013,6 +45030,7 @@ package android.view {
method public boolean dispatchDragEvent(android.view.DragEvent);
method protected void dispatchDraw(android.graphics.Canvas);
method public void dispatchDrawableHotspotChanged(float, float);
+ method public void dispatchFinishTemporaryDetach();
method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
@@ -45032,6 +45050,7 @@ package android.view {
method protected void dispatchSetActivated(boolean);
method protected void dispatchSetPressed(boolean);
method protected void dispatchSetSelected(boolean);
+ method public void dispatchStartTemporaryDetach();
method public void dispatchSystemUiVisibilityChanged(int);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
@@ -45244,6 +45263,7 @@ package android.view {
method public boolean isSelected();
method public boolean isShown();
method public boolean isSoundEffectsEnabled();
+ method public final boolean isTemporarilyDetached();
method public boolean isTextAlignmentResolved();
method public boolean isTextDirectionResolved();
method public boolean isVerticalFadingEdgeEnabled();
@@ -46831,8 +46851,6 @@ package android.view.accessibility {
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -47003,6 +47021,7 @@ package android.view.accessibility {
public final class AccessibilityWindowInfo implements android.os.Parcelable {
method public int describeContents();
+ method public android.view.accessibility.AccessibilityNodeInfo getAnchor();
method public void getBoundsInScreen(android.graphics.Rect);
method public android.view.accessibility.AccessibilityWindowInfo getChild(int);
method public int getChildCount();
@@ -47010,6 +47029,7 @@ package android.view.accessibility {
method public int getLayer();
method public android.view.accessibility.AccessibilityWindowInfo getParent();
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
+ method public java.lang.CharSequence getTitle();
method public int getType();
method public boolean isAccessibilityFocused();
method public boolean isActive();
@@ -48645,6 +48665,7 @@ package android.webkit {
method public int getPackageId(android.content.res.Resources, java.lang.String);
method public void invokeDrawGlFunctor(android.view.View, long, boolean);
method public boolean isTraceTagEnabled();
+ method public java.lang.Runnable setDrawGlFunctionDetachedCallback(android.view.View, java.lang.Runnable);
method public void setOnTraceEnabledChangeListener(android.webkit.WebViewDelegate.OnTraceEnabledChangeListener);
}
@@ -49354,7 +49375,7 @@ package android.widget {
method public long getMinDate();
method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
method public deprecated int getSelectedWeekBackgroundColor();
- method public boolean getShowWeekNumber();
+ method public deprecated boolean getShowWeekNumber();
method public deprecated int getShownWeekCount();
method public deprecated int getUnfocusedMonthDateColor();
method public int getWeekDayTextAppearance();
@@ -49371,7 +49392,7 @@ package android.widget {
method public deprecated void setSelectedDateVerticalBar(int);
method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
method public deprecated void setSelectedWeekBackgroundColor(int);
- method public void setShowWeekNumber(boolean);
+ method public deprecated void setShowWeekNumber(boolean);
method public deprecated void setShownWeekCount(int);
method public deprecated void setUnfocusedMonthDateColor(int);
method public void setWeekDayTextAppearance(int);
@@ -49518,21 +49539,21 @@ package android.widget {
ctor public DatePicker(android.content.Context, android.util.AttributeSet);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
- method public android.widget.CalendarView getCalendarView();
- method public boolean getCalendarViewShown();
+ method public deprecated android.widget.CalendarView getCalendarView();
+ method public deprecated boolean getCalendarViewShown();
method public int getDayOfMonth();
method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
- method public boolean getSpinnersShown();
+ method public deprecated boolean getSpinnersShown();
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
- method public void setCalendarViewShown(boolean);
+ method public deprecated void setCalendarViewShown(boolean);
method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
- method public void setSpinnersShown(boolean);
+ method public deprecated void setSpinnersShown(boolean);
method public void updateDate(int, int, int);
}
@@ -53104,6 +53125,7 @@ package java.lang {
method public static int compare(boolean, boolean);
method public int compareTo(java.lang.Boolean);
method public static boolean getBoolean(java.lang.String);
+ method public static int hashCode(boolean);
method public static boolean parseBoolean(java.lang.String);
method public static java.lang.String toString(boolean);
method public static java.lang.Boolean valueOf(boolean);
@@ -53121,6 +53143,7 @@ package java.lang {
method public static java.lang.Byte decode(java.lang.String) throws java.lang.NumberFormatException;
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(byte);
method public int intValue();
method public long longValue();
method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53129,6 +53152,7 @@ package java.lang {
method public static java.lang.Byte valueOf(byte);
method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Byte valueOf(java.lang.String) throws java.lang.NumberFormatException;
+ field public static final int BYTES = 1; // 0x1
field public static final byte MAX_VALUE = 127; // 0x7f
field public static final byte MIN_VALUE = -128; // 0xffffff80
field public static final int SIZE = 8; // 0x8
@@ -53166,6 +53190,7 @@ package java.lang {
method public static int getNumericValue(int);
method public static int getType(char);
method public static int getType(int);
+ method public static int hashCode(char);
method public static char highSurrogate(int);
method public static boolean isAlphabetic(int);
method public static boolean isBmpCodePoint(int);
@@ -53226,6 +53251,7 @@ package java.lang {
method public static char toUpperCase(char);
method public static int toUpperCase(int);
method public static java.lang.Character valueOf(char);
+ field public static final int BYTES = 2; // 0x2
field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
field public static final byte CONNECTOR_PUNCTUATION = 23; // 0x17
field public static final byte CONTROL = 15; // 0xf
@@ -53852,6 +53878,7 @@ package java.lang {
method public static int floatToIntBits(float);
method public static int floatToRawIntBits(float);
method public float floatValue();
+ method public static int hashCode(float);
method public static float intBitsToFloat(int);
method public int intValue();
method public static boolean isFinite(float);
@@ -53860,11 +53887,15 @@ package java.lang {
method public static boolean isNaN(float);
method public boolean isNaN();
method public long longValue();
+ method public static float max(float, float);
+ method public static float min(float, float);
method public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+ method public static float sum(float, float);
method public static java.lang.String toHexString(float);
method public static java.lang.String toString(float);
method public static java.lang.Float valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Float valueOf(float);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_EXPONENT = 127; // 0x7f
field public static final float MAX_VALUE = 3.4028235E38f;
field public static final int MIN_EXPONENT = -126; // 0xffffff82
@@ -54044,6 +54075,7 @@ package java.lang {
method public static java.lang.Long valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Long valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Long valueOf(long);
+ field public static final int BYTES = 8; // 0x8
field public static final long MAX_VALUE = 9223372036854775807L; // 0x7fffffffffffffffL
field public static final long MIN_VALUE = -9223372036854775808L; // 0x8000000000000000L
field public static final int SIZE = 64; // 0x40
@@ -54347,6 +54379,7 @@ package java.lang {
method public static java.lang.Short decode(java.lang.String) throws java.lang.NumberFormatException;
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(short);
method public int intValue();
method public long longValue();
method public static short parseShort(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -54356,6 +54389,7 @@ package java.lang {
method public static java.lang.Short valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Short valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Short valueOf(short);
+ field public static final int BYTES = 2; // 0x2
field public static final short MAX_VALUE = 32767; // 0x7fff
field public static final short MIN_VALUE = -32768; // 0xffff8000
field public static final int SIZE = 16; // 0x10
diff --git a/api/test-current.txt b/api/test-current.txt
index 09c55b927c60..a4408be22859 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2485,6 +2485,7 @@ package android {
field public static final int Widget_Material_CompoundButton_CheckBox = 16974435; // 0x1030263
field public static final int Widget_Material_CompoundButton_RadioButton = 16974436; // 0x1030264
field public static final int Widget_Material_CompoundButton_Star = 16974437; // 0x1030265
+ field public static final int Widget_Material_CompoundButton_Switch = 16974554; // 0x10302da
field public static final int Widget_Material_DatePicker = 16974438; // 0x1030266
field public static final int Widget_Material_DropDownItem = 16974439; // 0x1030267
field public static final int Widget_Material_DropDownItem_Spinner = 16974440; // 0x1030268
@@ -2519,6 +2520,7 @@ package android {
field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974500; // 0x10302a4
field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974501; // 0x10302a5
field public static final int Widget_Material_Light_CompoundButton_Star = 16974502; // 0x10302a6
+ field public static final int Widget_Material_Light_CompoundButton_Switch = 16974555; // 0x10302db
field public static final int Widget_Material_Light_DatePicker = 16974503; // 0x10302a7
field public static final int Widget_Material_Light_DropDownItem = 16974504; // 0x10302a8
field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974505; // 0x10302a9
@@ -4977,7 +4979,7 @@ package android.app {
field public int ledARGB;
field public int ledOffMS;
field public int ledOnMS;
- field public int number;
+ field public deprecated int number;
field public int priority;
field public android.app.Notification publicVersion;
field public android.net.Uri sound;
@@ -5024,11 +5026,13 @@ package android.app {
method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
method public java.lang.CharSequence getCancelLabel();
method public java.lang.CharSequence getConfirmLabel();
+ method public boolean getHintContentIntentLaunchesActivity();
method public java.lang.CharSequence getInProgressLabel();
method public boolean isAvailableOffline();
method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+ method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5070,7 +5074,7 @@ package android.app {
method public android.app.Notification.Builder setChronometerCountsDown(boolean);
method public android.app.Notification.Builder setColor(int);
method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
- method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
+ method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
@@ -5087,7 +5091,7 @@ package android.app {
method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
method public android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
- method public android.app.Notification.Builder setNumber(int);
+ method public deprecated android.app.Notification.Builder setNumber(int);
method public android.app.Notification.Builder setOngoing(boolean);
method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
method public android.app.Notification.Builder setPriority(int);
@@ -5205,6 +5209,7 @@ package android.app {
method public android.app.PendingIntent getDisplayIntent();
method public int getGravity();
method public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
method public boolean getHintHideIcon();
method public int getHintScreenTimeout();
method public boolean getHintShowBackgroundOnly();
@@ -5220,6 +5225,7 @@ package android.app {
method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
method public android.app.Notification.WearableExtender setGravity(int);
method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -5923,7 +5929,7 @@ package android.app.admin {
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
- method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
+ method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -7888,6 +7894,7 @@ package android.content {
method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+ method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -7918,6 +7925,8 @@ package android.content {
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+ field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
+ field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8528,8 +8537,9 @@ package android.content {
field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
- field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABLE = "android.intent.action.MANAGED_PROFILE_AVAILABLE";
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
@@ -20135,7 +20145,6 @@ package android.media {
}
public abstract class DrmInitData {
- ctor public DrmInitData();
method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
}
@@ -20390,8 +20399,8 @@ package android.media {
public class MediaActionSound {
ctor public MediaActionSound();
- method public synchronized void load(int);
- method public synchronized void play(int);
+ method public void load(int);
+ method public void play(int);
method public void release();
field public static final int FOCUS_COMPLETE = 1; // 0x1
field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -23514,6 +23523,7 @@ package android.net {
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static deprecated boolean isNetworkTypeValid(int);
+ method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
method public void releaseNetworkRequest(android.app.PendingIntent);
@@ -29139,6 +29149,7 @@ package android.os {
method public boolean isInteractive();
method public boolean isPowerSaveMode();
method public deprecated boolean isScreenOn();
+ method public boolean isSustainedPerformanceModeSupported();
method public boolean isWakeLockLevelSupported(int);
method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
method public void reboot(java.lang.String);
@@ -29766,7 +29777,6 @@ package android.preference {
method protected void onClick();
method protected android.view.View onCreateView(android.view.ViewGroup);
method public void onDependencyChanged(android.preference.Preference, boolean);
- method protected void onDetachedFromActivity();
method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
method public void onParentChanged(android.preference.Preference, boolean);
method protected void onPrepareForRemoval();
@@ -36690,7 +36700,6 @@ package android.telecom {
method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
method public boolean isInCall();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -37379,7 +37388,8 @@ package android.telephony {
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getGroupIdLevel1(int);
- method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
method public java.lang.String getLine1AlphaTag(int);
method public java.lang.String getLine1Number();
method public java.lang.String getLine1Number(int);
@@ -37448,6 +37458,13 @@ package android.telephony {
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+ field public static final int APPTYPE_CSIM = 4; // 0x4
+ field public static final int APPTYPE_ISIM = 5; // 0x5
+ field public static final int APPTYPE_RUIM = 3; // 0x3
+ field public static final int APPTYPE_SIM = 1; // 0x1
+ field public static final int APPTYPE_USIM = 2; // 0x2
+ field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+ field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -42347,6 +42364,7 @@ package android.view {
method public boolean dispatchDragEvent(android.view.DragEvent);
method protected void dispatchDraw(android.graphics.Canvas);
method public void dispatchDrawableHotspotChanged(float, float);
+ method public void dispatchFinishTemporaryDetach();
method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
@@ -42366,6 +42384,7 @@ package android.view {
method protected void dispatchSetActivated(boolean);
method protected void dispatchSetPressed(boolean);
method protected void dispatchSetSelected(boolean);
+ method public void dispatchStartTemporaryDetach();
method public void dispatchSystemUiVisibilityChanged(int);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
@@ -42578,6 +42597,7 @@ package android.view {
method public boolean isSelected();
method public boolean isShown();
method public boolean isSoundEffectsEnabled();
+ method public final boolean isTemporarilyDetached();
method public boolean isTextAlignmentResolved();
method public boolean isTextDirectionResolved();
method public boolean isVerticalFadingEdgeEnabled();
@@ -44162,8 +44182,6 @@ package android.view.accessibility {
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
- field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -44334,6 +44352,7 @@ package android.view.accessibility {
public final class AccessibilityWindowInfo implements android.os.Parcelable {
method public int describeContents();
+ method public android.view.accessibility.AccessibilityNodeInfo getAnchor();
method public void getBoundsInScreen(android.graphics.Rect);
method public android.view.accessibility.AccessibilityWindowInfo getChild(int);
method public int getChildCount();
@@ -44341,6 +44360,7 @@ package android.view.accessibility {
method public int getLayer();
method public android.view.accessibility.AccessibilityWindowInfo getParent();
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
+ method public java.lang.CharSequence getTitle();
method public int getType();
method public boolean isAccessibilityFocused();
method public boolean isActive();
@@ -46332,7 +46352,7 @@ package android.widget {
method public long getMinDate();
method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
method public deprecated int getSelectedWeekBackgroundColor();
- method public boolean getShowWeekNumber();
+ method public deprecated boolean getShowWeekNumber();
method public deprecated int getShownWeekCount();
method public deprecated int getUnfocusedMonthDateColor();
method public int getWeekDayTextAppearance();
@@ -46349,7 +46369,7 @@ package android.widget {
method public deprecated void setSelectedDateVerticalBar(int);
method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
method public deprecated void setSelectedWeekBackgroundColor(int);
- method public void setShowWeekNumber(boolean);
+ method public deprecated void setShowWeekNumber(boolean);
method public deprecated void setShownWeekCount(int);
method public deprecated void setUnfocusedMonthDateColor(int);
method public void setWeekDayTextAppearance(int);
@@ -46496,21 +46516,21 @@ package android.widget {
ctor public DatePicker(android.content.Context, android.util.AttributeSet);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
- method public android.widget.CalendarView getCalendarView();
- method public boolean getCalendarViewShown();
+ method public deprecated android.widget.CalendarView getCalendarView();
+ method public deprecated boolean getCalendarViewShown();
method public int getDayOfMonth();
method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
- method public boolean getSpinnersShown();
+ method public deprecated boolean getSpinnersShown();
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
- method public void setCalendarViewShown(boolean);
+ method public deprecated void setCalendarViewShown(boolean);
method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
- method public void setSpinnersShown(boolean);
+ method public deprecated void setSpinnersShown(boolean);
method public void updateDate(int, int, int);
}
@@ -48344,6 +48364,7 @@ package android.widget {
method public android.view.Menu getMenu();
method public java.lang.CharSequence getNavigationContentDescription();
method public android.graphics.drawable.Drawable getNavigationIcon();
+ method public android.view.View getNavigationView();
method public android.graphics.drawable.Drawable getOverflowIcon();
method public int getPopupTheme();
method public java.lang.CharSequence getSubtitle();
@@ -50082,6 +50103,7 @@ package java.lang {
method public static int compare(boolean, boolean);
method public int compareTo(java.lang.Boolean);
method public static boolean getBoolean(java.lang.String);
+ method public static int hashCode(boolean);
method public static boolean parseBoolean(java.lang.String);
method public static java.lang.String toString(boolean);
method public static java.lang.Boolean valueOf(boolean);
@@ -50099,6 +50121,7 @@ package java.lang {
method public static java.lang.Byte decode(java.lang.String) throws java.lang.NumberFormatException;
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(byte);
method public int intValue();
method public long longValue();
method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50107,6 +50130,7 @@ package java.lang {
method public static java.lang.Byte valueOf(byte);
method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Byte valueOf(java.lang.String) throws java.lang.NumberFormatException;
+ field public static final int BYTES = 1; // 0x1
field public static final byte MAX_VALUE = 127; // 0x7f
field public static final byte MIN_VALUE = -128; // 0xffffff80
field public static final int SIZE = 8; // 0x8
@@ -50144,6 +50168,7 @@ package java.lang {
method public static int getNumericValue(int);
method public static int getType(char);
method public static int getType(int);
+ method public static int hashCode(char);
method public static char highSurrogate(int);
method public static boolean isAlphabetic(int);
method public static boolean isBmpCodePoint(int);
@@ -50204,6 +50229,7 @@ package java.lang {
method public static char toUpperCase(char);
method public static int toUpperCase(int);
method public static java.lang.Character valueOf(char);
+ field public static final int BYTES = 2; // 0x2
field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
field public static final byte CONNECTOR_PUNCTUATION = 23; // 0x17
field public static final byte CONTROL = 15; // 0xf
@@ -50830,6 +50856,7 @@ package java.lang {
method public static int floatToIntBits(float);
method public static int floatToRawIntBits(float);
method public float floatValue();
+ method public static int hashCode(float);
method public static float intBitsToFloat(int);
method public int intValue();
method public static boolean isFinite(float);
@@ -50838,11 +50865,15 @@ package java.lang {
method public static boolean isNaN(float);
method public boolean isNaN();
method public long longValue();
+ method public static float max(float, float);
+ method public static float min(float, float);
method public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+ method public static float sum(float, float);
method public static java.lang.String toHexString(float);
method public static java.lang.String toString(float);
method public static java.lang.Float valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Float valueOf(float);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_EXPONENT = 127; // 0x7f
field public static final float MAX_VALUE = 3.4028235E38f;
field public static final int MIN_EXPONENT = -126; // 0xffffff82
@@ -51022,6 +51053,7 @@ package java.lang {
method public static java.lang.Long valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Long valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Long valueOf(long);
+ field public static final int BYTES = 8; // 0x8
field public static final long MAX_VALUE = 9223372036854775807L; // 0x7fffffffffffffffL
field public static final long MIN_VALUE = -9223372036854775808L; // 0x8000000000000000L
field public static final int SIZE = 64; // 0x40
@@ -51325,6 +51357,7 @@ package java.lang {
method public static java.lang.Short decode(java.lang.String) throws java.lang.NumberFormatException;
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(short);
method public int intValue();
method public long longValue();
method public static short parseShort(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -51334,6 +51367,7 @@ package java.lang {
method public static java.lang.Short valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Short valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Short valueOf(short);
+ field public static final int BYTES = 2; // 0x2
field public static final short MAX_VALUE = 32767; // 0x7fff
field public static final short MIN_VALUE = -32768; // 0xffff8000
field public static final int SIZE = 16; // 0x10
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 221b2d36fcec..456be02021e0 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -44,6 +44,7 @@ import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.IPackageManager;
+import android.content.pm.InstrumentationInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
@@ -96,6 +97,7 @@ public class Am extends BaseCommand {
private static final int STACK_BOUNDS_INSET = 10;
private IActivityManager mAm;
+ private IPackageManager mPm;
private int mStartFlags = 0;
private boolean mWaitOption = false;
@@ -224,7 +226,8 @@ public class Am extends BaseCommand {
" --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
"\n" +
"am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" +
- " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" +
+ " is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there \n" +
+ " is only one instrumentation. Options are:\n" +
" -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" +
" [-e perf true] to generate raw output for performance measurements.\n" +
" -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" +
@@ -373,6 +376,12 @@ public class Am extends BaseCommand {
throw new AndroidException("Can't connect to activity manager; is the system running?");
}
+ mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ if (mPm == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException("Can't connect to package manager; is the system running?");
+ }
+
String op = nextArgRequired();
if (op.equals("start")) {
@@ -570,13 +579,7 @@ public class Am extends BaseCommand {
if (intent.getComponent() != null) {
packageName = intent.getComponent().getPackageName();
} else {
- IPackageManager pm = IPackageManager.Stub.asInterface(
- ServiceManager.getService("package"));
- if (pm == null) {
- System.err.println("Error: Package manager not running; aborting");
- return;
- }
- List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
+ List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
mUserId).getList();
if (activities == null || activities.size() <= 0) {
System.err.println("Error: Intent does not match any activities: "
@@ -813,8 +816,44 @@ public class Am extends BaseCommand {
}
String cnArg = nextArgRequired();
- ComponentName cn = ComponentName.unflattenFromString(cnArg);
- if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+
+ ComponentName cn;
+ if (cnArg.contains("/")) {
+ cn = ComponentName.unflattenFromString(cnArg);
+ if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+ } else {
+ List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList();
+
+ final int numInfos = infos == null ? 0: infos.size();
+ List<ComponentName> cns = new ArrayList<>();
+ for (int i = 0; i < numInfos; i++) {
+ InstrumentationInfo info = infos.get(i);
+
+ ComponentName c = new ComponentName(info.packageName, info.name);
+ if (cnArg.equals(info.packageName)) {
+ cns.add(c);
+ }
+ }
+
+ if (cns.size() == 0) {
+ throw new IllegalArgumentException("No instrumentation found for: " + cnArg);
+ } else if (cns.size() == 1) {
+ cn = cns.get(0);
+ } else {
+ StringBuilder cnsStr = new StringBuilder();
+ final int numCns = cns.size();
+ for (int i = 0; i < numCns; i++) {
+ cnsStr.append(cns.get(i).flattenToString());
+ cnsStr.append(", ");
+ }
+
+ // Remove last ", "
+ cnsStr.setLength(cnsStr.length() - 2);
+
+ throw new IllegalArgumentException("Found multiple instrumentations: "
+ + cnsStr.toString());
+ }
+ }
InstrumentationWatcher watcher = null;
UiAutomationConnection connection = null;
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index b208e438f171..0e674c864137 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -88,6 +88,8 @@ public final class Sm {
runForget();
} else if ("set-emulate-fbe".equals(op)) {
runSetEmulateFbe();
+ } else if ("get-fbe-mode".equals(op)) {
+ runGetFbeMode();
} else {
throw new IllegalArgumentException();
}
@@ -145,6 +147,16 @@ public final class Sm {
StorageManager.DEBUG_EMULATE_FBE);
}
+ public void runGetFbeMode() {
+ if (StorageManager.isFileEncryptedNativeOnly()) {
+ System.out.println("native");
+ } else if (StorageManager.isFileEncryptedEmulatedOnly()) {
+ System.out.println("emulated");
+ } else {
+ System.out.println("none");
+ }
+ }
+
public void runPartition() throws RemoteException {
final String diskId = nextArg();
final String type = nextArg();
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 4019a56133b4..ee03280578e5 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -36,11 +36,11 @@ import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import com.android.internal.R;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -319,6 +319,9 @@ public class AccessibilityServiceInfo implements Parcelable {
*/
public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040;
+ /** {@hide} */
+ public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
+
/**
* The event types an {@link AccessibilityService} is interested in.
* <p>
@@ -687,8 +690,9 @@ public class AccessibilityServiceInfo implements Parcelable {
}
/** {@hide} */
- public boolean isEncryptionAware() {
- return mResolveInfo.serviceInfo.directBootAware;
+ public boolean isDirectBootAware() {
+ return ((flags & FLAG_FORCE_DIRECT_BOOT_AWARE) != 0)
+ || mResolveInfo.serviceInfo.directBootAware;
}
/**
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index 7a0c89b75a4a..e18a34de3f91 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -36,8 +36,7 @@ import java.util.List;
* Accessibility services with the
* {@link android.R.styleable#AccessibilityService_canPerformGestures} property can dispatch
* gestures. This class describes those gestures. Gestures are made up of one or more strokes.
- * Gestures are immutable; use the {@code create} methods to get common gesture, or a
- * {@code Builder} to create a new one.
+ * Gestures are immutable once built.
* <p>
* Spatial dimensions throughout are in screen pixels. Time is measured in milliseconds.
*/
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 336218522c77..65d48e609618 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -95,7 +95,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
}
return sSystemReady;
}
- static boolean sSystemReady = false;
+ static volatile boolean sSystemReady = false;
static public void broadcastStickyIntent(Intent intent, String permission, int userId) {
broadcastStickyIntent(intent, permission, AppOpsManager.OP_NONE, userId);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5b94696c1461..14c4fc6451fc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -91,6 +91,7 @@ import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.SuperNotCalledException;
+import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.ThreadedRenderer;
import android.view.View;
@@ -4632,7 +4633,21 @@ public final class ActivityThread {
}
if (reportToActivity) {
- cb.onConfigurationChanged(newConfig);
+ Configuration configToReport = newConfig;
+
+ if (cb instanceof ContextThemeWrapper) {
+ // ContextThemeWrappers may override the configuration for that context.
+ // We must check and apply any overrides defined.
+ ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb;
+ final Configuration localOverrideConfig =
+ contextThemeWrapper.getOverrideConfiguration();
+ if (localOverrideConfig != null) {
+ configToReport = new Configuration(newConfig);
+ configToReport.updateFrom(localOverrideConfig);
+ }
+ }
+
+ cb.onConfigurationChanged(configToReport);
}
if (activity != null) {
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 3a51aff37921..1e2cc2662018 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -146,6 +146,10 @@ final class BackStackState implements Parcelable {
op.removed.add(r);
}
}
+ bse.mEnterAnim = op.enterAnim;
+ bse.mExitAnim = op.exitAnim;
+ bse.mPopEnterAnim = op.popEnterAnim;
+ bse.mPopExitAnim = op.popExitAnim;
bse.addOp(op);
num++;
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index c745644adf13..2a04c39f2c5a 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1033,7 +1033,8 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* false if it is not.
*/
public void setUserVisibleHint(boolean isVisibleToUser) {
- if (!mUserVisibleHint && isVisibleToUser && mState < STARTED && isAdded()) {
+ if (!mUserVisibleHint && isVisibleToUser && mState < STARTED
+ && mFragmentManager != null && isAdded()) {
mFragmentManager.performPendingDeferredStart(this);
}
mUserVisibleHint = isVisibleToUser;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8423de882782..2e4a8c6d82e9 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -174,6 +174,9 @@ public class Notification implements Parcelable
* <li>Notification of an ongoing countdown timer should be stamped with the timer's end time.
* </ul>
*
+ * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is not shown
+ * anymore by default and must be opted into by using
+ * {@link android.app.Notification.Builder#setShowWhen(boolean)}
*/
public long when;
@@ -206,6 +209,8 @@ public class Notification implements Parcelable
* {@link Notification.Builder} has displayed the number in the expanded notification view.
*
* If the number is 0 or negative, it is never shown.
+ *
+ * @deprecated this number is not shown anymore
*/
public int number;
@@ -1205,6 +1210,7 @@ public class Notification implements Parcelable
// Flags bitwise-ored to mFlags
private static final int FLAG_AVAILABLE_OFFLINE = 0x1;
+ private static final int FLAG_HINT_LAUNCHES_ACTIVITY = 1 << 1;
// Default value for flags integer
private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE;
@@ -1367,6 +1373,30 @@ public class Notification implements Parcelable
public CharSequence getCancelLabel() {
return mCancelLabel;
}
+
+ /**
+ * Set a hint that this Action will launch an {@link Activity} directly, telling the
+ * platform that it can generate the appropriate transitions.
+ * @param hintLaunchesActivity {@code true} if the content intent will launch
+ * an activity and transitions should be generated, false otherwise.
+ * @return this object for method chaining
+ */
+ public WearableExtender setHintContentIntentLaunchesActivity(
+ boolean hintLaunchesActivity) {
+ setFlag(FLAG_HINT_LAUNCHES_ACTIVITY, hintLaunchesActivity);
+ return this;
+ }
+
+ /**
+ * Get a hint that this Action will launch an {@link Activity} directly, telling the
+ * platform that it can generate the appropriate transitions
+ * @return {@code true} if the content intent will launch an activity and transitions
+ * should be generated, false otherwise. The default value is {@code false} if this was
+ * never set.
+ */
+ public boolean getHintContentIntentLaunchesActivity() {
+ return (mFlags & FLAG_HINT_LAUNCHES_ACTIVITY) != 0;
+ }
}
}
@@ -2133,7 +2163,9 @@ public class Notification implements Parcelable
if (toAdopt == null) {
mN = new Notification();
- mN.extras.putBoolean(EXTRA_SHOW_WHEN, true);
+ if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+ mN.extras.putBoolean(EXTRA_SHOW_WHEN, true);
+ }
mN.priority = PRIORITY_DEFAULT;
mN.visibility = VISIBILITY_PRIVATE;
} else {
@@ -2183,8 +2215,10 @@ public class Notification implements Parcelable
/**
* Add a timestamp pertaining to the notification (usually the time the event occurred).
- * It will be shown in the notification content view by default; use
- * {@link #setShowWhen(boolean) setShowWhen} to control this.
+ *
+ * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is not
+ * shown anymore by default and must be opted into by using
+ * {@link android.app.Notification.Builder#setShowWhen(boolean)}
*
* @see Notification#when
*/
@@ -2196,6 +2230,8 @@ public class Notification implements Parcelable
/**
* Control whether the timestamp set with {@link #setWhen(long) setWhen} is shown
* in the content view.
+ * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this defaults to
+ * {@code false}. For earlier apps, the default is {@code true}.
*/
public Builder setShowWhen(boolean show) {
mN.extras.putBoolean(EXTRA_SHOW_WHEN, show);
@@ -2304,9 +2340,22 @@ public class Notification implements Parcelable
}
/**
- * Set the third line of text in the platform notification template.
- * Don't use if you're also using {@link #setProgress(int, int, boolean)}; they occupy the
- * same location in the standard template.
+ * This provides some additional information that is displayed in the notification. No
+ * guarantees are given where exactly it is displayed.
+ *
+ * <p>This information should only be provided if it provides an essential
+ * benefit to the understanding of the notification. The more text you provide the
+ * less readable it becomes. For example, an email client should only provide the account
+ * name here if more than one email account has been added.</p>
+ *
+ * <p>As of {@link android.os.Build.VERSION_CODES#N} this information is displayed in the
+ * notification header area.
+ *
+ * On Android versions before {@link android.os.Build.VERSION_CODES#N}
+ * this will be shown in the third line of text in the platform notification template.
+ * You should not be using {@link #setProgress(int, int, boolean)} at the
+ * same time on those versions; they occupy the same place.
+ * </p>
*/
public Builder setSubText(CharSequence text) {
mN.extras.putCharSequence(EXTRA_SUB_TEXT, safeCharSequence(text));
@@ -2345,6 +2394,8 @@ public class Notification implements Parcelable
* Set the large number at the right-hand side of the notification. This is
* equivalent to setContentInfo, although it might show the number in a different
* font size for readability.
+ *
+ * @deprecated this number is not shown anywhere anymore
*/
public Builder setNumber(int number) {
mN.number = number;
@@ -2356,6 +2407,10 @@ public class Notification implements Parcelable
*
* The platform template will draw this on the last line of the notification, at the far
* right (to the right of a smallIcon if it has been placed there).
+ *
+ * @deprecated use {@link #setSubText(CharSequence)} instead to set a text in the header.
+ * For legacy apps targeting a version below {@link android.os.Build.VERSION_CODES#N} this
+ * field will still show up, but the subtext will take precedence.
*/
public Builder setContentInfo(CharSequence info) {
mN.extras.putCharSequence(EXTRA_INFO_TEXT, safeCharSequence(info));
@@ -3009,10 +3064,8 @@ public class Notification implements Parcelable
contentView.setBoolean(R.id.notification_header, "setExpanded", false);
contentView.setTextViewText(R.id.app_name_text, null);
contentView.setViewVisibility(R.id.chronometer, View.GONE);
- contentView.setViewVisibility(R.id.header_sub_text, View.GONE);
- contentView.setViewVisibility(R.id.header_content_info, View.GONE);
- contentView.setViewVisibility(R.id.sub_text_divider, View.GONE);
- contentView.setViewVisibility(R.id.content_info_divider, View.GONE);
+ contentView.setViewVisibility(R.id.header_text, View.GONE);
+ contentView.setViewVisibility(R.id.header_text_divider, View.GONE);
contentView.setViewVisibility(R.id.time_divider, View.GONE);
contentView.setImageViewIcon(R.id.profile_badge, null);
contentView.setViewVisibility(R.id.profile_badge, View.GONE);
@@ -3112,39 +3165,12 @@ public class Notification implements Parcelable
private void bindNotificationHeader(RemoteViews contentView) {
bindSmallIcon(contentView);
bindHeaderAppName(contentView);
- bindHeaderSubText(contentView);
- bindContentInfo(contentView);
+ bindHeaderText(contentView);
bindHeaderChronometerAndTime(contentView);
bindExpandButton(contentView);
bindProfileBadge(contentView);
}
- private void bindContentInfo(RemoteViews contentView) {
- boolean visible = false;
- if (mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
- contentView.setTextViewText(R.id.header_content_info,
- processLegacyText(mN.extras.getCharSequence(EXTRA_INFO_TEXT)));
- contentView.setViewVisibility(R.id.header_content_info, View.VISIBLE);
- visible = true;
- } else if (mN.number > 0) {
- final int tooBig = mContext.getResources().getInteger(
- R.integer.status_bar_notification_info_maxnum);
- if (mN.number > tooBig) {
- contentView.setTextViewText(R.id.header_content_info, processLegacyText(
- mContext.getResources().getString(
- R.string.status_bar_notification_info_overflow)));
- } else {
- contentView.setTextViewText(R.id.header_content_info,
- processLegacyText(String.valueOf(mN.number)));
- }
- contentView.setViewVisibility(R.id.header_content_info, View.VISIBLE);
- visible = true;
- }
- if (visible) {
- contentView.setViewVisibility(R.id.content_info_divider, View.VISIBLE);
- }
- }
-
private void bindExpandButton(RemoteViews contentView) {
contentView.setDrawableParameters(R.id.expand_button, false, -1, resolveContrastColor(),
PorterDuff.Mode.SRC_ATOP, -1);
@@ -3169,17 +3195,22 @@ public class Notification implements Parcelable
}
}
- private void bindHeaderSubText(RemoteViews contentView) {
- CharSequence subText = mN.extras.getCharSequence(EXTRA_SUB_TEXT);
- if (subText == null && mStyle != null && mStyle.mSummaryTextSet
+ private void bindHeaderText(RemoteViews contentView) {
+ CharSequence headerText = mN.extras.getCharSequence(EXTRA_SUB_TEXT);
+ if (headerText == null && mStyle != null && mStyle.mSummaryTextSet
&& mStyle.hasSummaryInHeader()) {
- subText = mStyle.mSummaryText;
+ headerText = mStyle.mSummaryText;
}
- if (subText != null) {
+ if (headerText == null
+ && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
+ && mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
+ headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
+ }
+ if (headerText != null) {
// TODO: Remove the span entirely to only have the string with propper formating.
- contentView.setTextViewText(R.id.header_sub_text, processLegacyText(subText));
- contentView.setViewVisibility(R.id.header_sub_text, View.VISIBLE);
- contentView.setViewVisibility(R.id.sub_text_divider, View.VISIBLE);
+ contentView.setTextViewText(R.id.header_text, processLegacyText(headerText));
+ contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
+ contentView.setViewVisibility(R.id.header_text_divider, View.VISIBLE);
}
}
@@ -4863,6 +4894,7 @@ public class Notification implements Parcelable
private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
private static final int FLAG_HINT_AVOID_BACKGROUND_CLIPPING = 1 << 4;
+ private static final int FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY = 1 << 6;
// Default value for flags integer
private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
@@ -5429,6 +5461,29 @@ public class Notification implements Parcelable
return mHintScreenTimeout;
}
+ /**
+ * Set a hint that this notification's content intent will launch an {@link Activity}
+ * directly, telling the platform that it can generate the appropriate transitions.
+ * @param hintContentIntentLaunchesActivity {@code true} if the content intent will launch
+ * an activity and transitions should be generated, false otherwise.
+ * @return this object for method chaining
+ */
+ public WearableExtender setHintContentIntentLaunchesActivity(
+ boolean hintContentIntentLaunchesActivity) {
+ setFlag(FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY, hintContentIntentLaunchesActivity);
+ return this;
+ }
+
+ /**
+ * Get a hint that this notification's content intent will launch an {@link Activity}
+ * directly, telling the platform that it can generate the appropriate transitions
+ * @return {@code true} if the content intent will launch an activity and transitions should
+ * be generated, false otherwise. The default value is {@code false} if this was never set.
+ */
+ public boolean getHintContentIntentLaunchesActivity() {
+ return (mFlags & FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY) != 0;
+ }
+
private void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 0d4729d8349f..47bff6440332 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -153,25 +153,31 @@ public class NotificationManager
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
- * Normal interruption filter.
+ * Normal interruption filter - no notifications are suppressed.
*/
public static final int INTERRUPTION_FILTER_ALL = 1;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
- * Priority interruption filter.
+ * Priority interruption filter - all notifications are suppressed except those that match
+ * the priority criteria. Some audio streams are muted. See
+ * {@link Policy#priorityCallSenders}, {@link Policy#priorityCategories},
+ * {@link Policy#priorityMessageSenders} to define or query this criteria. Users can
+ * additionally specify packages that can bypass this interruption filter.
*/
public static final int INTERRUPTION_FILTER_PRIORITY = 2;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
- * No interruptions filter.
+ * No interruptions filter - all notifications are suppressed and all audio streams (except
+ * those used for phone calls) and vibrations are muted.
*/
public static final int INTERRUPTION_FILTER_NONE = 3;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
- * Alarms only interruption filter.
+ * Alarms only interruption filter - all notifications except those of category
+ * {@link Notification#CATEGORY_ALARM} are suppressed. Some audio streams are muted.
*/
public static final int INTERRUPTION_FILTER_ALARMS = 4;
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 276f774a8f4e..2c1ee8e13624 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -36,6 +36,7 @@ import android.view.WindowAnimationFrameStats;
import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
+
import libcore.io.IoUtils;
import java.io.FileOutputStream;
@@ -77,6 +78,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
private int mOwningUid;
+ @Override
public void connect(IAccessibilityServiceClient client, int flags) {
if (client == null) {
throw new IllegalArgumentException("Client cannot be null!");
@@ -326,11 +328,12 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
int flags) {
IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
- AccessibilityServiceInfo info = new AccessibilityServiceInfo();
+ final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
- | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
+ | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS
+ | AccessibilityServiceInfo.FLAG_FORCE_DIRECT_BOOT_AWARE;
info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 45aa6b44a8f1..96757bba510d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2185,9 +2185,6 @@ public class DevicePolicyManager {
* Force a new device unlock password (the password needed to access the entire device, not for
* individual accounts) on the user. This takes effect immediately.
* <p>
- * Calling this from a managed profile that shares the password with the owner profile will
- * throw a security exception.
- * <p>
* <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
* device admins that are not device owner and not profile owner.
* The password can now only be changed if there is currently no password set. Device owner
@@ -2201,10 +2198,10 @@ public class DevicePolicyManager {
* case the currently active quality will be increased to match.
* <p>
* Calling with a null or empty password will clear any existing PIN, pattern or password if the
- * current password constraints allow it. <em>Note: This will not
- * work in {@link android.os.Build.VERSION_CODES#N} and later for device admins that are not
- * device owner and not profile owner. Once set, the password cannot be changed to null or
- * empty, except by device owner or profile owner.</em>
+ * current password constraints allow it. <em>Note: This will not work in
+ * {@link android.os.Build.VERSION_CODES#N} and later for managed profiles, or for device admins
+ * that are not device owner or profile owner. Once set, the password cannot be changed to null
+ * or empty except by these admins.</em>
* <p>
* The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call this method; if it has
@@ -2291,6 +2288,23 @@ public class DevicePolicyManager {
}
/**
+ * Returns maximum time to lock that applied by all profiles in this user. We do this because we
+ * do not have a separate timeout to lock for work challenge only.
+ *
+ * @hide
+ */
+ public long getMaximumTimeToLockForUserAndProfiles(int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getMaximumTimeToLockForUserAndProfiles(userHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return 0;
+ }
+
+ /**
* Make the device lock immediately, as if the lock screen timeout has expired at the point of
* this call.
* <p>
@@ -2980,17 +2994,21 @@ public class DevicePolicyManager {
* @return {@code true} if the package is set as always-on VPN controller; {@code false}
* otherwise.
* @throws SecurityException if {@code admin} is not a device or a profile owner.
+ * @throws NameNotFoundException if {@code vpnPackage} is not installed.
+ * @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being
+ * set as always-on, or if always-on VPN is not available.
*/
- public boolean setAlwaysOnVpnPackage(@NonNull ComponentName admin,
- @Nullable String vpnPackage) {
+ public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage)
+ throws NameNotFoundException, UnsupportedOperationException {
if (mService != null) {
try {
- return mService.setAlwaysOnVpnPackage(admin, vpnPackage);
+ if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage)) {
+ throw new NameNotFoundException(vpnPackage);
+ }
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- return false;
}
/**
@@ -4159,6 +4177,10 @@ public class DevicePolicyManager {
* The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method;
* if not, a security exception will be thrown.
+ * <p>
+ * This method can be called on the {@link DevicePolicyManager} instance returned by
+ * {@link #getParentProfileInstance(ComponentName)} in order to set the configuration for
+ * the parent profile.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param target Component name of the agent to be enabled.
@@ -4179,7 +4201,7 @@ public class DevicePolicyManager {
@NonNull ComponentName target, PersistableBundle configuration) {
if (mService != null) {
try {
- mService.setTrustAgentConfiguration(admin, target, configuration);
+ mService.setTrustAgentConfiguration(admin, target, configuration, mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4190,6 +4212,10 @@ public class DevicePolicyManager {
* Gets configuration for the given trust agent based on aggregating all calls to
* {@link #setTrustAgentConfiguration(ComponentName, ComponentName, PersistableBundle)} for
* all device admins.
+ * <p>
+ * This method can be called on the {@link DevicePolicyManager} instance returned by
+ * {@link #getParentProfileInstance(ComponentName)} in order to retrieve the configuration set
+ * on the parent profile.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with. If null,
* this function returns a list of configurations for all admins that declare
@@ -4210,7 +4236,8 @@ public class DevicePolicyManager {
@NonNull ComponentName agent, int userHandle) {
if (mService != null) {
try {
- return mService.getTrustAgentConfiguration(admin, agent, userHandle);
+ return mService.getTrustAgentConfiguration(admin, agent, userHandle,
+ mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -5852,8 +5879,43 @@ public class DevicePolicyManager {
/**
* Called by the profile owner of a managed profile to obtain a {@link DevicePolicyManager}
* whose calls act on the parent profile.
- * <p>
- * Note only some methods will work on the parent Manager.
+ *
+ * <p>The following methods are supported for the parent instance, all other methods will
+ * throw a SecurityException when called on the parent instance:
+ * <ul>
+ * <li>{@link #getPasswordQuality}</li>
+ * <li>{@link #setPasswordQuality}</li>
+ * <li>{@link #getPasswordMinimumLength}</li>
+ * <li>{@link #setPasswordMinimumLength}</li>
+ * <li>{@link #getPasswordMinimumUpperCase}</li>
+ * <li>{@link #setPasswordMinimumUpperCase}</li>
+ * <li>{@link #getPasswordMinimumLowerCase}</li>
+ * <li>{@link #setPasswordMinimumLowerCase}</li>
+ * <li>{@link #getPasswordMinimumLetters}</li>
+ * <li>{@link #setPasswordMinimumLetters}</li>
+ * <li>{@link #getPasswordMinimumNumeric}</li>
+ * <li>{@link #setPasswordMinimumNumeric}</li>
+ * <li>{@link #getPasswordMinimumSymbols}</li>
+ * <li>{@link #setPasswordMinimumSymbols}</li>
+ * <li>{@link #getPasswordMinimumNonLetter}</li>
+ * <li>{@link #setPasswordMinimumNonLetter}</li>
+ * <li>{@link #getPasswordHistoryLength}</li>
+ * <li>{@link #setPasswordHistoryLength}</li>
+ * <li>{@link #getPasswordExpirationTimeout}</li>
+ * <li>{@link #setPasswordExpirationTimeout}</li>
+ * <li>{@link #getPasswordExpiration}</li>
+ * <li>{@link #isActivePasswordSufficient}</li>
+ * <li>{@link #getCurrentFailedPasswordAttempts}</li>
+ * <li>{@link #getMaximumFailedPasswordsForWipe}</li>
+ * <li>{@link #setMaximumFailedPasswordsForWipe}</li>
+ * <li>{@link #getMaximumTimeToLock}</li>
+ * <li>{@link #setMaximumTimeToLock}</li>
+ * <li>{@link #lockNow}</li>
+ * <li>{@link #getKeyguardDisabledFeatures}</li>
+ * <li>{@link #setKeyguardDisabledFeatures}</li>
+ * <li>{@link #getTrustAgentConfiguration}</li>
+ * <li>{@link #setTrustAgentConfiguration}</li>
+ * </ul>
*
* @return a new instance of {@link DevicePolicyManager} that acts on the parent profile.
* @throws SecurityException if {@code admin} is not a profile owner.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6ee56aa91296..6df10388b85e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -80,6 +80,7 @@ interface IDevicePolicyManager {
void setMaximumTimeToLock(in ComponentName who, long timeMs, boolean parent);
long getMaximumTimeToLock(in ComponentName who, int userHandle, boolean parent);
+ long getMaximumTimeToLockForUserAndProfiles(int userHandle);
void lockNow(boolean parent);
@@ -228,9 +229,9 @@ interface IDevicePolicyManager {
boolean getBluetoothContactSharingDisabledForUser(int userId);
void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
- in PersistableBundle args);
+ in PersistableBundle args, boolean parent);
List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
- in ComponentName agent, int userId);
+ in ComponentName agent, int userId, boolean parent);
boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName);
boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName);
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 801c9517b64d..8e515e2b579c 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -427,23 +427,31 @@ public abstract class BackupAgent extends ContextWrapper {
}
/**
- * Tells the application agent that the backup data size exceeded current transport quota.
- * Later calls to {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
- * and {@link #onFullBackup(FullBackupDataOutput)} could use this information
- * to reduce backup size under the limit.
- * However, the quota can change, so do not assume that the value passed in here is absolute,
- * similarly all subsequent backups should not be restricted to this size.
- * This callback will be invoked before data has been put onto the wire in a preflight check,
- * so it is relatively inexpensive to hit your quota.
- * Apps that hit quota repeatedly without dealing with it can be subject to having their backup
- * schedule reduced.
- * The {@code quotaBytes} is a loose guideline b/c of metadata added by the backupmanager
- * so apps should be more aggressive in trimming their backup set.
+ * Notification that the application's current backup operation causes it to exceed
+ * the maximum size permitted by the transport. The ongoing backup operation is
+ * halted and rolled back: any data that had been stored by a previous backup operation
+ * is still intact. Typically the quota-exceeded state will be detected before any data
+ * is actually transmitted over the network.
*
- * @param backupDataBytes Expected or already processed amount of data.
- * Could be less than total backup size if backup process was interrupted
- * before finish of processing all backup data.
- * @param quotaBytes Current amount of backup data that is allowed for the app.
+ * <p>The {@code quotaBytes} value is the total data size currently permitted for this
+ * application. If desired, the application can use this as a hint for determining
+ * how much data to store. For example, a messaging application might choose to
+ * store only the newest messages, dropping enough older content to stay under
+ * the quota.
+ *
+ * <p class="note">Note that the maximum quota for the application can change over
+ * time. In particular, in the future the quota may grow. Applications that adapt
+ * to the quota when deciding what data to store should be aware of this and implement
+ * their data storage mechanisms in a way that can take advantage of additional
+ * quota.
+ *
+ * @param backupDataBytes The amount of data measured while initializing the backup
+ * operation, if the total exceeds the app's alloted quota. If initial measurement
+ * suggested that the data would fit but then too much data was actually submitted
+ * as part of the operation, then this value is the amount of data that had been
+ * streamed into the transport at the time the quota was reached.
+ * @param quotaBytes The maximum data size that the transport currently permits
+ * this application to store as a backup.
*/
public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
}
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 1af495365825..2d9f4a71b005 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -17,8 +17,7 @@
package android.appwidget;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.List;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,7 +34,9 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.util.DisplayMetrics;
+import android.util.SparseArray;
import android.util.TypedValue;
import android.widget.RemoteViews;
import android.widget.RemoteViews.OnClickHandler;
@@ -62,7 +63,7 @@ public class AppWidgetHost {
private final Handler mHandler;
private final int mHostId;
private final Callbacks mCallbacks;
- private final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<>();
+ private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>();
private OnClickHandler mOnClickHandler;
static class Callbacks extends IAppWidgetHost.Stub {
@@ -164,7 +165,6 @@ public class AppWidgetHost {
bindService();
}
-
private static void bindService() {
synchronized (sServiceLock) {
if (sService == null) {
@@ -179,17 +179,25 @@ public class AppWidgetHost {
* becomes visible, i.e. from onStart() in your Activity.
*/
public void startListening() {
- int[] updatedIds;
- ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
+ final int[] idsToUpdate;
+ synchronized (mViews) {
+ int N = mViews.size();
+ idsToUpdate = new int[N];
+ for (int i = 0; i < N; i++) {
+ idsToUpdate[i] = mViews.keyAt(i);
+ }
+ }
+ List<RemoteViews> updatedViews;
+ int[] updatedIds = new int[idsToUpdate.length];
try {
- updatedIds = sService.startListening(mCallbacks, mContextOpPackageName, mHostId,
- updatedViews);
+ updatedViews = sService.startListening(
+ mCallbacks, mContextOpPackageName, mHostId, idsToUpdate, updatedIds).getList();
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
- final int N = updatedIds.length;
+ int N = updatedViews.size();
for (int i = 0; i < N; i++) {
updateAppWidgetView(updatedIds[i], updatedViews.get(i));
}
@@ -206,10 +214,6 @@ public class AppWidgetHost {
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
-
- // This is here because keyguard needs it since it'll be switching users after this call.
- // If it turns out other apps need to call this often, we should re-think how this works.
- clearViews();
}
/**
@@ -418,7 +422,9 @@ public class AppWidgetHost {
* Clear the list of Views that have been created by this AppWidgetHost.
*/
protected void clearViews() {
- mViews.clear();
+ synchronized (mViews) {
+ mViews.clear();
+ }
}
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index d762a1727272..2a7eff883095 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -36,6 +36,7 @@ import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.Pair;
@@ -1015,6 +1016,8 @@ public final class BluetoothAdapter {
try {
if (mService != null) {
return mService.factoryReset();
+ } else {
+ SystemProperties.set("persist.bluetooth.factoryreset", "true");
}
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index cd67b3ee8a3e..4db45670dd85 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -17,6 +17,7 @@
package android.content;
import android.accounts.Account;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -60,6 +61,8 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@@ -289,6 +292,31 @@ public abstract class ContentResolver {
/** @hide */
public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
+ /** @hide */
+ @IntDef(flag = true,
+ value = {
+ NOTIFY_SYNC_TO_NETWORK,
+ NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NotifyFlags {}
+
+ /**
+ * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: attempt to sync the change
+ * to the network.
+ */
+ public static final int NOTIFY_SYNC_TO_NETWORK = 1<<0;
+
+ /**
+ * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: if set, this notification
+ * will be skipped if it is being delivered to the root URI of a ContentObserver that is
+ * using "notify for descendants." The purpose of this is to allow the provide to send
+ * a general notification of "something under X" changed that observers of that specific
+ * URI can receive, while also sending a specific URI under X. It would use this flag
+ * when sending the former, so that observers of "X and descendants" only see the latter.
+ */
+ public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1;
+
// Always log queries which take 500ms+; shorter queries are
// sampled accordingly.
private static final boolean ENABLE_CONTENT_SAMPLE = false;
@@ -1676,7 +1704,7 @@ public abstract class ContentResolver {
* The observer that originated the change will only receive the notification if it
* has requested to receive self-change notifications by implementing
* {@link ContentObserver#deliverSelfNotifications()} to return true.
- * @param syncToNetwork If true, attempt to sync the change to the network.
+ * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
@@ -1690,6 +1718,32 @@ public abstract class ContentResolver {
}
/**
+ * Notify registered observers that a row was updated.
+ * To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}.
+ * By default, CursorAdapter objects will get this notification.
+ * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
+ * adapter that's registered for the authority of the provided uri. No account will be
+ * passed to the sync adapter, so all matching accounts will be synchronized.
+ *
+ * @param uri The uri of the content that was changed.
+ * @param observer The observer that originated the change, may be <code>null</null>.
+ * The observer that originated the change will only receive the notification if it
+ * has requested to receive self-change notifications by implementing
+ * {@link ContentObserver#deliverSelfNotifications()} to return true.
+ * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
+ * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
+ */
+ public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
+ @NotifyFlags int flags) {
+ Preconditions.checkNotNull(uri, "uri");
+ notifyChange(
+ ContentProvider.getUriWithoutUserId(uri),
+ observer,
+ flags,
+ ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
+ }
+
+ /**
* Notify registered observers within the designated user(s) that a row was updated.
*
* @hide
@@ -1699,7 +1753,24 @@ public abstract class ContentResolver {
try {
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
- observer != null && observer.deliverSelfNotifications(), syncToNetwork,
+ observer != null && observer.deliverSelfNotifications(),
+ syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
+ userHandle);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Notify registered observers within the designated user(s) that a row was updated.
+ *
+ * @hide
+ */
+ public void notifyChange(Uri uri, ContentObserver observer, @NotifyFlags int flags,
+ @UserIdInt int userHandle) {
+ try {
+ getContentService().notifyChange(
+ uri, observer == null ? null : observer.getContentObserver(),
+ observer != null && observer.deliverSelfNotifications(), flags,
userHandle);
} catch (RemoteException e) {
}
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index d47e780fa4d2..3446e0315a1d 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -52,7 +52,7 @@ interface IContentService {
* USER_CURRENT are properly interpreted.
*/
void notifyChange(in Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, boolean syncToNetwork,
+ boolean observerWantsSelfNotifications, int flags,
int userHandle);
void requestSync(in Account account, String authority, in Bundle extras);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 10259be8d430..30f2c948df96 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3056,15 +3056,29 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_MANAGED_PROFILE_UNLOCKED =
"android.intent.action.MANAGED_PROFILE_UNLOCKED";
+ /** @hide */
+ public static final String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED =
+ "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+
/**
- * Broadcast sent to the primary user when an associated managed profile's availability has
- * changed. This includes when the user toggles the profile's quiet mode. Carries an extra
+ * Broadcast sent to the primary user when an associated managed profile has become available.
+ * Currently this includes when the user disables quiet mode for the profile. Carries an extra
* {@link #EXTRA_USER} that specifies the UserHandle of the profile. When quiet mode is changed,
* this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the new state
* of quiet mode. This is only sent to registered receivers, not manifest receivers.
*/
- public static final String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED =
- "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+ public static final String ACTION_MANAGED_PROFILE_AVAILABLE =
+ "android.intent.action.MANAGED_PROFILE_AVAILABLE";
+
+ /**
+ * Broadcast sent to the primary user when an associated managed profile has become unavailable.
+ * Currently this includes when the user enables quiet mode for the profile. Carries an extra
+ * {@link #EXTRA_USER} that specifies the UserHandle of the profile. When quiet mode is changed,
+ * this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the new state
+ * of quiet mode. This is only sent to registered receivers, not manifest receivers.
+ */
+ public static final String ACTION_MANAGED_PROFILE_UNAVAILABLE =
+ "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
/**
* Sent when the user taps on the clock widget in the system's "quick settings" area.
@@ -4165,6 +4179,9 @@ public class Intent implements Parcelable, Cloneable {
/**
* Optional boolean extra indicating whether quiet mode has been switched on or off.
+ * When a profile goes into quiet mode, all apps in the profile are killed and the
+ * profile user is stopped. Widgets originating from the profile are masked, and app
+ * launcher icons are grayed out.
*/
public static final String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 3a17e23b0547..22ab43bbb429 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -449,11 +449,12 @@ public class IntentFilter implements Parcelable {
}
/**
- * Modify priority of this filter. The default priority is 0. Positive
- * values will be before the default, lower values will be after it.
- * Applications must use a value that is larger than
- * {@link #SYSTEM_LOW_PRIORITY} and smaller than
- * {@link #SYSTEM_HIGH_PRIORITY} .
+ * Modify priority of this filter. This only affects receiver filters.
+ * The priority of activity filters are set in XML and cannot be changed
+ * programatically. The default priority is 0. Positive values will be
+ * before the default, lower values will be after it. Applications should
+ * use a value that is larger than {@link #SYSTEM_LOW_PRIORITY} and
+ * smaller than {@link #SYSTEM_HIGH_PRIORITY} .
*
* @param priority The new priority value.
*
@@ -883,6 +884,15 @@ public class IntentFilter implements Parcelable {
return true;
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof AuthorityEntry) {
+ final AuthorityEntry other = (AuthorityEntry)obj;
+ return match(other);
+ }
+ return false;
+ }
+
/**
* Determine whether this AuthorityEntry matches the given data Uri.
* <em>Note that this comparison is case-sensitive, unlike formal
@@ -917,7 +927,7 @@ public class IntentFilter implements Parcelable {
}
return MATCH_CATEGORY_HOST;
}
- };
+ }
/**
* Add a new Intent data "scheme specific part" to match against. The filter must
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ea251f648034..fe8db9f6ad37 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1096,13 +1096,19 @@ public class PackageParser {
pkg.mSignatures = null;
pkg.mSigningKeys = null;
- collectCertificates(pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags);
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
+ try {
+ collectCertificates(
+ pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags);
- if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
- for (int i = 0; i < pkg.splitCodePaths.length; i++) {
- collectCertificates(pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i],
- parseFlags);
+ if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
+ for (int i = 0; i < pkg.splitCodePaths.length; i++) {
+ collectCertificates(
+ pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], parseFlags);
+ }
}
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
@@ -1118,6 +1124,7 @@ public class PackageParser {
Certificate[][] allSignersCerts = null;
Signature[] signatures = null;
try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
signatures = convertToSignatures(allSignersCerts);
// APK verified using APK Signature Scheme v2.
@@ -1130,6 +1137,8 @@ public class PackageParser {
"Failed to collect certificates from " + apkPath
+ " using APK Signature Scheme v2",
e);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
if (verified) {
@@ -1186,7 +1195,7 @@ public class PackageParser {
}
// APK's integrity needs to be verified using JAR signature scheme.
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "buildVerifyList");
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
final List<ZipEntry> toVerify = new ArrayList<>();
toVerify.add(manifestEntry);
@@ -1208,7 +1217,6 @@ public class PackageParser {
toVerify.add(entry);
}
}
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (!codeFound && requireCode) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
@@ -1218,7 +1226,6 @@ public class PackageParser {
// Verify that entries are signed consistently with the first entry
// we encountered. Note that for splits, certificates may have
// already been populated during an earlier parse of a base APK.
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyEntries");
for (ZipEntry entry : toVerify) {
final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
if (ArrayUtils.isEmpty(entryCerts)) {
@@ -1300,7 +1307,12 @@ public class PackageParser {
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
// TODO: factor signature related items out of Package object
final Package tempPkg = new Package(null);
- collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/);
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
+ try {
+ collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
signatures = tempPkg.mSignatures;
} else {
signatures = null;
@@ -5531,7 +5543,7 @@ public class PackageParser {
return pi;
}
- public final static class Instrumentation extends Component {
+ public final static class Instrumentation extends Component<IntentInfo> {
public final InstrumentationInfo info;
public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 387fda717e48..93fe73b06e89 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -714,12 +714,11 @@ public class Resources {
* the resource ID passed here is an alias to another Drawable resource.
* This means that if the density configuration of the alias resource
* is different than the actual resource, the density of the returned
- * Drawable would be incorrect, resulting in bad scaling. To work
- * around this, you can instead retrieve the Drawable through
- * {@link TypedArray#getDrawable TypedArray.getDrawable}. Use
- * {@link android.content.Context#obtainStyledAttributes(int[])
- * Context.obtainStyledAttributes} with
- * an array containing the resource ID of interest to create the TypedArray.</p>
+ * Drawable would be incorrect, resulting in bad scaling. To work
+ * around this, you can instead manually resolve the aliased reference
+ * by using {@link #getValue(int, TypedValue, boolean)} and passing
+ * {@code true} for {@code resolveRefs}. The resulting
+ * {@link TypedValue#resourceId} value may be passed to this method.</p>
*
* <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
* {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index 2dce4257da57..b2288fc4492d 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -136,12 +136,14 @@ public class DdmHandleHello extends ChunkHandler {
}
String vmFlags = "CheckJNI="
+ (vmRuntime.isCheckJniEnabled() ? "true" : "false");
+ boolean isNativeDebuggable = vmRuntime.isNativeDebuggable();
ByteBuffer out = ByteBuffer.allocate(28
+ vmIdent.length() * 2
+ appName.length() * 2
+ instructionSetDescription.length() * 2
- + vmFlags.length() * 2);
+ + vmFlags.length() * 2
+ + 1);
out.order(ChunkHandler.CHUNK_ORDER);
out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
out.putInt(android.os.Process.myPid());
@@ -154,6 +156,7 @@ public class DdmHandleHello extends ChunkHandler {
putString(out, instructionSetDescription);
out.putInt(vmFlags.length());
putString(out, vmFlags);
+ out.put((byte)(isNativeDebuggable ? 1 : 0));
Chunk reply = new Chunk(CHUNK_HELO, out);
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 4add9626b24e..d06e08b70910 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2025,11 +2025,20 @@ public abstract class CameraMetadata<TKey> {
* produced in response to a capture request submitted
* while in HDR mode.</p>
* <p>Since substantial post-processing is generally needed to
- * produce an HDR image, only YUV and JPEG outputs are
- * supported for LIMITED/FULL device HDR captures, and only
- * JPEG outputs are supported for LEGACY HDR
- * captures. Using a RAW output for HDR capture is not
+ * produce an HDR image, only YUV, PRIVATE, and JPEG
+ * outputs are supported for LIMITED/FULL device HDR
+ * captures, and only JPEG outputs are supported for LEGACY
+ * HDR captures. Using a RAW output for HDR capture is not
* supported.</p>
+ * <p>Some devices may also support always-on HDR, which
+ * applies HDR processing at full frame rate. For these
+ * devices, intents other than STILL_CAPTURE will also
+ * produce an HDR output with no frame rate impact compared
+ * to normal operation, though the quality may be lower
+ * than for STILL_CAPTURE intents.</p>
+ * <p>If SCENE_MODE_HDR is used with unsupported output types
+ * or capture intents, the images captured will be as if
+ * the SCENE_MODE was not enabled at all.</p>
*
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
* @see CaptureRequest#CONTROL_SCENE_MODE
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 5748726b4cad..4f41e1c60d86 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3373,7 +3373,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
/**
* <p>Maximum raw value output by sensor for this frame.</p>
- * <p>Since the android.sensor.blackLevel may change for different
+ * <p>Since the {@link CameraCharacteristics#SENSOR_BLACK_LEVEL_PATTERN android.sensor.blackLevelPattern} may change for different
* capture settings (e.g., {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}), the white
* level will change accordingly. This key is similar to
* {@link CameraCharacteristics#SENSOR_INFO_WHITE_LEVEL android.sensor.info.whiteLevel}, but specifies the camera device
@@ -3385,6 +3385,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* &gt;= 0</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#SENSOR_BLACK_LEVEL_PATTERN
* @see CameraCharacteristics#SENSOR_INFO_WHITE_LEVEL
* @see CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS
* @see CaptureRequest#SENSOR_SENSITIVITY
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index d84a6fcbd16f..d2e820e17776 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -974,6 +974,7 @@ public class CameraDeviceImpl extends CameraDevice
if (mRemoteDevice != null) {
mRemoteDevice.disconnect();
+ mRemoteDevice.unlinkToDeath(this, /*flags*/0);
}
// Only want to fire the onClosed callback once;
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index ddc3fd12b70d..ef5f6d71b8b6 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -31,6 +31,7 @@ import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.SubmitInfo;
+import android.os.IBinder;
import android.os.RemoteException;
import android.view.Surface;
@@ -53,6 +54,12 @@ public class ICameraDeviceUserWrapper {
mRemoteDevice = remoteDevice;
}
+ public void unlinkToDeath(IBinder.DeathRecipient recipient, int flags) {
+ if (mRemoteDevice.asBinder() != null) {
+ mRemoteDevice.asBinder().unlinkToDeath(recipient, flags);
+ }
+ }
+
public void disconnect() {
try {
mRemoteDevice.disconnect();
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
index 2c2ad1c23ce6..b0b94e3ac009 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
@@ -70,7 +70,7 @@ public class CameraDeviceState {
* CameraDeviceStateListener callbacks to be called after state transitions.
*/
public interface CameraDeviceStateListener {
- void onError(int errorCode, RequestHolder holder);
+ void onError(int errorCode, Object errorArg, RequestHolder holder);
void onConfiguring();
void onIdle();
void onBusy();
@@ -162,11 +162,12 @@ public class CameraDeviceState {
* @param captureError Report a recoverable error for a single buffer or result using a valid
* error code for {@code ICameraDeviceCallbacks}, or
* {@link #NO_CAPTURE_ERROR}.
+ * @param captureErrorArg An argument for some error captureError codes.
* @return {@code false} if an error has occurred.
*/
public synchronized boolean setCaptureResult(final RequestHolder request,
- final CameraMetadataNative result,
- final int captureError) {
+ final CameraMetadataNative result,
+ final int captureError, final Object captureErrorArg) {
if (mCurrentState != STATE_CAPTURING) {
Log.e(TAG, "Cannot receive result while in state: " + mCurrentState);
mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
@@ -179,7 +180,7 @@ public class CameraDeviceState {
mCurrentHandler.post(new Runnable() {
@Override
public void run() {
- mCurrentListener.onError(captureError, request);
+ mCurrentListener.onError(captureError, captureErrorArg, request);
}
});
} else {
@@ -194,6 +195,11 @@ public class CameraDeviceState {
return mCurrentError == NO_CAPTURE_ERROR;
}
+ public synchronized boolean setCaptureResult(final RequestHolder request,
+ final CameraMetadataNative result) {
+ return setCaptureResult(request, result, NO_CAPTURE_ERROR, /*errorArg*/null);
+ }
+
/**
* Set the listener for state transition callbacks.
*
@@ -239,7 +245,7 @@ public class CameraDeviceState {
mCurrentHandler.post(new Runnable() {
@Override
public void run() {
- mCurrentListener.onError(mCurrentError, mCurrentRequest);
+ mCurrentListener.onError(mCurrentError, /*errorArg*/null, mCurrentRequest);
}
});
}
@@ -299,7 +305,7 @@ public class CameraDeviceState {
mCurrentHandler.post(new Runnable() {
@Override
public void run() {
- mCurrentListener.onError(error, mCurrentRequest);
+ mCurrentListener.onError(error, /*errorArg*/null, mCurrentRequest);
}
});
} else {
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index d01c275e74dc..f99928a884ee 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -480,19 +480,15 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
- ArrayList<Surface> surfaces = null;
+ SparseArray<Surface> surfaces = null;
synchronized(mConfigureLock) {
if (!mConfiguring) {
String err = "Cannot end configure, no configuration change in progress.";
Log.e(TAG, err);
throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
- int numSurfaces = mSurfaces.size();
- if (numSurfaces > 0) {
- surfaces = new ArrayList<>();
- for (int i = 0; i < numSurfaces; ++i) {
- surfaces.add(mSurfaces.valueAt(i));
- }
+ if (mSurfaces != null) {
+ surfaces = mSurfaces.clone();
}
mConfiguring = false;
}
diff --git a/core/java/android/hardware/camera2/legacy/CaptureCollector.java b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
index eb48a01ac103..113927c4c4b2 100644
--- a/core/java/android/hardware/camera2/legacy/CaptureCollector.java
+++ b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
@@ -19,7 +19,7 @@ import android.hardware.camera2.impl.CameraDeviceImpl;
import android.util.Log;
import android.util.MutableLong;
import android.util.Pair;
-
+import android.view.Surface;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.TreeSet;
@@ -95,22 +95,28 @@ public class CaptureCollector {
} else {
// Send buffer dropped errors for each pending buffer if the request has
// started.
- if (mFailedPreview) {
- Log.w(TAG, "Preview buffers dropped for request: " +
- mRequest.getRequestId());
- for (int i = 0; i < mRequest.numPreviewTargets(); i++) {
- CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
- /*result*/null,
- CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER);
- }
- }
- if (mFailedJpeg) {
- Log.w(TAG, "Jpeg buffers dropped for request: " +
- mRequest.getRequestId());
- for (int i = 0; i < mRequest.numJpegTargets(); i++) {
- CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
- /*result*/null,
- CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER);
+ for (Surface targetSurface : mRequest.getRequest().getTargets() ) {
+ try {
+ if (mRequest.jpegType(targetSurface)) {
+ if (mFailedJpeg) {
+ CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
+ /*result*/null,
+ CameraDeviceImpl.CameraDeviceCallbacks.
+ ERROR_CAMERA_BUFFER,
+ targetSurface);
+ }
+ } else {
+ // preview buffer
+ if (mFailedPreview) {
+ CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
+ /*result*/null,
+ CameraDeviceImpl.CameraDeviceCallbacks.
+ ERROR_CAMERA_BUFFER,
+ targetSurface);
+ }
+ }
+ } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+ Log.e(TAG, "Unexpected exception when querying Surface: " + e);
}
}
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 661edd734a71..6c9586986b97 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -36,6 +36,7 @@ import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
+import android.util.SparseArray;
import android.view.Surface;
import java.util.ArrayList;
@@ -64,7 +65,7 @@ public class LegacyCameraDevice implements AutoCloseable {
private final CameraCharacteristics mStaticCharacteristics;
private final ICameraDeviceCallbacks mDeviceCallbacks;
private final CameraDeviceState mDeviceState = new CameraDeviceState();
- private List<Surface> mConfiguredSurfaces;
+ private SparseArray<Surface> mConfiguredSurfaces;
private boolean mClosed = false;
private final ConditionVariable mIdle = new ConditionVariable(/*open*/true);
@@ -89,13 +90,29 @@ public class LegacyCameraDevice implements AutoCloseable {
public static final int NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1;
private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
+ return getExtrasFromRequest(holder,
+ /*errorCode*/CameraDeviceState.NO_CAPTURE_ERROR, /*errorArg*/null);
+ }
+
+ private CaptureResultExtras getExtrasFromRequest(RequestHolder holder,
+ int errorCode, Object errorArg) {
+ int errorStreamId = -1;
+ if (errorCode == CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER) {
+ Surface errorTarget = (Surface) errorArg;
+ int indexOfTarget = mConfiguredSurfaces.indexOfValue(errorTarget);
+ if (indexOfTarget < 0) {
+ Log.e(TAG, "Buffer drop error reported for unknown Surface");
+ } else {
+ errorStreamId = mConfiguredSurfaces.keyAt(indexOfTarget);
+ }
+ }
if (holder == null) {
return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
}
return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
/*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
- /*partialResultCount*/1, /*errorStreamId*/-1);
+ /*partialResultCount*/1, errorStreamId);
}
/**
@@ -105,9 +122,9 @@ public class LegacyCameraDevice implements AutoCloseable {
private final CameraDeviceState.CameraDeviceStateListener mStateListener =
new CameraDeviceState.CameraDeviceStateListener() {
@Override
- public void onError(final int errorCode, final RequestHolder holder) {
+ public void onError(final int errorCode, final Object errorArg, final RequestHolder holder) {
if (DEBUG) {
- Log.d(TAG, "onError called, errorCode = " + errorCode);
+ Log.d(TAG, "onError called, errorCode = " + errorCode + ", errorArg = " + errorArg);
}
switch (errorCode) {
/*
@@ -125,7 +142,7 @@ public class LegacyCameraDevice implements AutoCloseable {
}
}
- final CaptureResultExtras extras = getExtrasFromRequest(holder);
+ final CaptureResultExtras extras = getExtrasFromRequest(holder, errorCode, errorArg);
mResultHandler.post(new Runnable() {
@Override
public void run() {
@@ -281,14 +298,17 @@ public class LegacyCameraDevice implements AutoCloseable {
*
* <p>Every surface in {@code outputs} must be non-{@code null}.</p>
*
- * @param outputs a list of surfaces to set.
+ * @param outputs a list of surfaces to set. LegacyCameraDevice will take ownership of this
+ * list; it must not be modified by the caller once it's passed in.
* @return an error code for this binder operation, or {@link NO_ERROR}
* on success.
*/
- public int configureOutputs(List<Surface> outputs) {
+ public int configureOutputs(SparseArray<Surface> outputs) {
List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>();
if (outputs != null) {
- for (Surface output : outputs) {
+ int count = outputs.size();
+ for (int i = 0; i < count; i++) {
+ Surface output = outputs.valueAt(i);
if (output == null) {
Log.e(TAG, "configureOutputs - null outputs are not allowed");
return BAD_VALUE;
@@ -353,7 +373,7 @@ public class LegacyCameraDevice implements AutoCloseable {
}
if (success) {
- mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
+ mConfiguredSurfaces = outputs;
} else {
return LegacyExceptionUtils.INVALID_OPERATION;
}
@@ -659,6 +679,23 @@ public class LegacyCameraDevice implements AutoCloseable {
return nativeGetSurfaceId(surface);
}
+ static List<Long> getSurfaceIds(SparseArray<Surface> surfaces) {
+ if (surfaces == null) {
+ throw new NullPointerException("Null argument surfaces");
+ }
+ List<Long> surfaceIds = new ArrayList<>();
+ int count = surfaces.size();
+ for (int i = 0; i < count; i++) {
+ long id = getSurfaceId(surfaces.valueAt(i));
+ if (id == 0) {
+ throw new IllegalStateException(
+ "Configured surface had null native GraphicBufferProducer pointer!");
+ }
+ surfaceIds.add(id);
+ }
+ return surfaceIds;
+ }
+
static List<Long> getSurfaceIds(Collection<Surface> surfaces) {
if (surfaces == null) {
throw new NullPointerException("Null argument surfaces");
diff --git a/core/java/android/hardware/camera2/legacy/RequestHolder.java b/core/java/android/hardware/camera2/legacy/RequestHolder.java
index 9b628fb72490..476c3debc571 100644
--- a/core/java/android/hardware/camera2/legacy/RequestHolder.java
+++ b/core/java/android/hardware/camera2/legacy/RequestHolder.java
@@ -41,6 +41,8 @@ public class RequestHolder {
private final int mNumPreviewTargets;
private volatile boolean mFailed = false;
+ private final Collection<Long> mJpegSurfaceIds;
+
/**
* A builder class for {@link RequestHolder} objects.
*
@@ -150,13 +152,13 @@ public class RequestHolder {
*/
public RequestHolder build(long frameNumber) {
return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber,
- mNumJpegTargets, mNumPreviewTargets);
+ mNumJpegTargets, mNumPreviewTargets, mJpegSurfaceIds);
}
}
private RequestHolder(int requestId, int subsequenceId, CaptureRequest request,
boolean repeating, long frameNumber, int numJpegTargets,
- int numPreviewTargets) {
+ int numPreviewTargets, Collection<Long> jpegSurfaceIds) {
mRepeating = repeating;
mRequest = request;
mRequestId = requestId;
@@ -164,6 +166,7 @@ public class RequestHolder {
mFrameNumber = frameNumber;
mNumJpegTargets = numJpegTargets;
mNumPreviewTargets = numPreviewTargets;
+ mJpegSurfaceIds = jpegSurfaceIds;
}
/**
@@ -238,6 +241,17 @@ public class RequestHolder {
}
/**
+ * Returns true if the given surface requires jpeg buffers.
+ *
+ * @param s a {@link android.view.Surface} to check.
+ * @return true if the surface requires a jpeg buffer.
+ */
+ public boolean jpegType(Surface s)
+ throws LegacyExceptionUtils.BufferQueueAbandonedException {
+ return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds);
+ }
+
+ /**
* Mark this request as failed.
*/
public void failRequest() {
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index e8ce3ec7aaa9..a3fdd56cc65c 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -908,8 +908,7 @@ public class RequestThreadManager {
mFaceDetectMapper.mapResultFaces(result, mLastRequest);
if (!holder.requestFailed()) {
- mDeviceState.setCaptureResult(holder, result,
- CameraDeviceState.NO_CAPTURE_ERROR);
+ mDeviceState.setCaptureResult(holder, result);
}
}
if (DEBUG) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index b8088f32ecaf..4756b3728009 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -815,7 +815,8 @@ public class FingerprintManager {
if (groupId != reqGroupId) {
Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
}
- mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint);
+ mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
+ deviceId));
}
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index fbac58c039c6..47440de62827 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,9 +16,7 @@
package android.hardware.input;
-import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.os.SomeArgs;
-import com.android.internal.util.ArrayUtils;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 014e73fd8aeb..10fc8e6e366a 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -52,4 +52,11 @@ public abstract class InputManagerInternal {
*/
public abstract void onInputMethodSubtypeChanged(int userId,
@Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype);
+
+ /**
+ * Toggles Caps Lock state for input device with specific id.
+ *
+ * @param deviceId The id of input device.
+ */
+ public abstract void toggleCapsLock(int deviceId);
}
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index ae44f1d68c3c..194b9ee58780 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -345,6 +345,24 @@ public class ContextHubInfo {
mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length);
}
+ @Override
+ public String toString() {
+ String retVal = "";
+ retVal += "Id : " + mId;
+ retVal += ", Name : " + mName;
+ retVal += "\n\tVendor : " + mVendor;
+ retVal += ", ToolChain : " + mToolchain;
+ retVal += "\n\tPlatformVersion : " + mPlatformVersion;
+ retVal += ", StaticSwVersion : " + mStaticSwVersion;
+ retVal += "\n\tPeakMips : " + mPeakMips;
+ retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW";
+ retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW";
+ retVal += "\n\tSupported sensors : " + Arrays.toString(mSupportedSensors);
+ retVal += "\n\tMemory Regions : " + Arrays.toString(mMemoryRegions);
+
+ return retVal;
+ }
+
private ContextHubInfo(Parcel in) {
mId = in.readInt();
mName = in.readString();
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index b65e24e3b81e..2b9b97463888 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -18,9 +18,12 @@ package android.hardware.location;
import android.Manifest;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -28,18 +31,17 @@ import java.util.HashMap;
* @hide
*/
public class ContextHubService extends IContextHubService.Stub {
-
public static final String CONTEXTHUB_SERVICE = "contexthub_service";
private static final String TAG = "ContextHubService";
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
- + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
+ + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
public static final int ANY_HUB = -1;
- public static final int MSG_LOAD_NANO_APP = 5;
- public static final int MSG_UNLOAD_NANO_APP = 2;
+ public static final int MSG_LOAD_NANO_APP = 3;
+ public static final int MSG_UNLOAD_NANO_APP = 4;
private static final String PRE_LOADED_GENERIC_UNKNOWN = "Preloaded app, unknown";
private static final String PRE_LOADED_APP_NAME = PRE_LOADED_GENERIC_UNKNOWN;
@@ -78,8 +80,8 @@ public class ContextHubService extends IContextHubService.Stub {
@Override
public int registerCallback(IContextHubCallback callback) throws RemoteException {
checkPermissions();
- synchronized(this) {
- mCallback = callback;
+ synchronized (this) {
+ mCallback = callback;
}
return 0;
}
@@ -87,10 +89,10 @@ public class ContextHubService extends IContextHubService.Stub {
@Override
public int[] getContextHubHandles() throws RemoteException {
checkPermissions();
- int [] returnArray = new int[mContextHubInfo.length];
+ int[] returnArray = new int[mContextHubInfo.length];
for (int i = 0; i < returnArray.length; ++i) {
- returnArray[i] = i + 1; //valid handles from 1...n
+ returnArray[i] = i;
Log.d(TAG, String.format("Hub %s is mapped to %d",
mContextHubInfo[i].getName(), returnArray[i]));
}
@@ -101,7 +103,6 @@ public class ContextHubService extends IContextHubService.Stub {
@Override
public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
checkPermissions();
- contextHubHandle -= 1;
if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
return null; // null means fail
}
@@ -112,13 +113,12 @@ public class ContextHubService extends IContextHubService.Stub {
@Override
public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
checkPermissions();
- contextHubHandle -= 1;
if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
- return -1; // negative handle are invalid, means failed
+ Log.e(TAG, "Invalid contextHubhandle " + contextHubHandle);
+ return -1;
}
- // Call Native interface here
int[] msgHeader = new int[MSG_HEADER_SIZE];
msgHeader[MSG_FIELD_HUB_HANDLE] = contextHubHandle;
msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
@@ -147,7 +147,7 @@ public class ContextHubService extends IContextHubService.Stub {
msgHeader[MSG_FIELD_VERSION] = 0;
msgHeader[MSG_FIELD_TYPE] = MSG_UNLOAD_NANO_APP;
- if(nativeSendMessage(msgHeader, null) != 0) {
+ if (nativeSendMessage(msgHeader, null) != 0) {
return -1;
}
@@ -157,7 +157,7 @@ public class ContextHubService extends IContextHubService.Stub {
@Override
public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
- throws RemoteException {
+ throws RemoteException {
checkPermissions();
// This assumes that all the nanoAppInfo is current. This is reasonable
// for the use cases for tightly controlled nanoApps.
@@ -173,10 +173,10 @@ public class ContextHubService extends IContextHubService.Stub {
checkPermissions();
ArrayList<Integer> foundInstances = new ArrayList<Integer>();
- for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
+ for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
- if (filter.testMatch(info)){
+ if (filter.testMatch(info)) {
foundInstances.add(nanoAppInstance);
}
}
@@ -191,7 +191,7 @@ public class ContextHubService extends IContextHubService.Stub {
@Override
public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
- throws RemoteException {
+ throws RemoteException {
checkPermissions();
int[] msgHeader = new int[MSG_HEADER_SIZE];
@@ -203,6 +203,32 @@ public class ContextHubService extends IContextHubService.Stub {
return nativeSendMessage(msgHeader, msg.getData());
}
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump contexthub_service");
+ return;
+ }
+
+ pw.println("Dumping ContextHub Service");
+
+ pw.println("");
+ // dump ContextHubInfo
+ pw.println("=================== CONTEXT HUBS ====================");
+ for (int i = 0; i < mContextHubInfo.length; i++) {
+ pw.println("Handle " + i + " : " + mContextHubInfo[i].toString());
+ }
+ pw.println("");
+ pw.println("=================== NANOAPPS ====================");
+ // Dump nanoAppHash
+ for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
+ pw.println(nanoAppInstance + " : " + mNanoAppHash.get(nanoAppInstance).toString());
+ }
+
+ // dump eventLog
+ }
+
private void checkPermissions() {
mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
}
@@ -212,16 +238,16 @@ public class ContextHubService extends IContextHubService.Stub {
return -1;
}
- synchronized(this) {
+ synchronized (this) {
if (mCallback != null) {
ContextHubMessage msg = new ContextHubMessage(header[MSG_FIELD_TYPE],
- header[MSG_FIELD_VERSION],
- data);
+ header[MSG_FIELD_VERSION],
+ data);
try {
mCallback.onMessageReceipt(header[MSG_FIELD_HUB_HANDLE],
- header[MSG_FIELD_APP_INSTANCE],
- msg);
+ header[MSG_FIELD_APP_INSTANCE],
+ msg);
} catch (Exception e) {
Log.w(TAG, "Exception " + e + " when calling remote callback");
return -1;
diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java
index d100de257549..857434ea75b9 100644
--- a/core/java/android/hardware/location/MemoryRegion.java
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -79,6 +79,33 @@ public class MemoryRegion implements Parcelable{
}
@Override
+ public String toString() {
+ String mask = "";
+
+ if (isReadable()) {
+ mask += "r";
+ } else {
+ mask += "-";
+ }
+
+ if (isWritable()) {
+ mask += "w";
+ } else {
+ mask += "-";
+ }
+
+ if (isExecutable()) {
+ mask += "x";
+ } else {
+ mask += "-";
+ }
+
+ String retVal = "[ " + mSizeBytesFree + "/ " + mSizeBytes + " ] : " + mask;
+
+ return retVal;
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index b447b6245712..c8f3439aee70 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -284,4 +284,14 @@ public class NanoApp {
return new NanoApp[size];
}
};
+
+ @Override
+ public String toString() {
+ String retVal = "Id : " + mAppId;
+ retVal += ", Version : " + mAppVersion;
+ retVal += ", Name : " + mName;
+ retVal += ", Publisher : " + mPublisher;
+
+ return retVal;
+ }
}
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
index 977f645db199..e842ec65a3e7 100644
--- a/core/java/android/hardware/location/NanoAppInstanceInfo.java
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -320,4 +320,15 @@ public class NanoAppInstanceInfo {
return new NanoAppInstanceInfo[size];
}
};
+
+ @Override
+ public String toString() {
+ String retVal = "handle : " + mHandle;
+ retVal += ", Id : 0x" + Long.toHexString(mAppId);
+ retVal += ", Version : " + mAppVersion;
+ retVal += ", Name : " + mName;
+ retVal += ", Publisher : " + mPublisher;
+
+ return retVal;
+ }
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6b79a8ac438a..cc201bc78bb5 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -295,9 +295,7 @@ public class InputMethodService extends AbstractInputMethodService {
boolean mLastShowInputRequested;
int mCandidatesVisibility;
CompletionInfo[] mCurCompletions;
-
- boolean mShowInputForced;
-
+
boolean mFullscreenApplied;
boolean mIsFullscreen;
View mExtractView;
@@ -422,7 +420,6 @@ public class InputMethodService extends AbstractInputMethodService {
boolean wasVis = isInputViewShown();
mShowInputFlags = 0;
mShowInputRequested = false;
- mShowInputForced = false;
doHideWindow();
clearInsetOfPreviousIme();
if (resultReceiver != null) {
@@ -439,8 +436,7 @@ public class InputMethodService extends AbstractInputMethodService {
public void showSoftInput(int flags, ResultReceiver resultReceiver) {
if (DEBUG) Log.v(TAG, "showSoftInput()");
boolean wasVis = isInputViewShown();
- mShowInputFlags = 0;
- if (onShowInputRequested(flags, false)) {
+ if (dispatchOnShowInputRequested(flags, false)) {
try {
showWindow(true);
} catch (BadTokenException e) {
@@ -721,7 +717,11 @@ public class InputMethodService extends AbstractInputMethodService {
mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(),
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ?
ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE;
- mService.updateInputViewShown();
+ // In Android M and prior, state change of
+ // Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD has triggered
+ // #onConfigurationChanged(). For compatibility reasons, we reset the internal
+ // state as if configuration was changed.
+ mService.resetStateForNewConfiguration();
}
}
@@ -817,8 +817,8 @@ public class InputMethodService extends AbstractInputMethodService {
mInitialized = false;
mWindowCreated = false;
mShowInputRequested = false;
- mShowInputForced = false;
-
+ mShowInputFlags = 0;
+
mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
mRootView = mInflater.inflate(
com.android.internal.R.layout.input_method, null);
@@ -888,7 +888,10 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@Override public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
-
+ resetStateForNewConfiguration();
+ }
+
+ private void resetStateForNewConfiguration() {
boolean visible = mWindowVisible;
int showFlags = mShowInputFlags;
boolean showingInput = mShowInputRequested;
@@ -903,7 +906,7 @@ public class InputMethodService extends AbstractInputMethodService {
if (visible) {
if (showingInput) {
// If we were last showing the soft keyboard, try to do so again.
- if (onShowInputRequested(showFlags, true)) {
+ if (dispatchOnShowInputRequested(showFlags, true)) {
showWindow(true);
if (completions != null) {
mCurCompletions = completions;
@@ -1540,20 +1543,41 @@ public class InputMethodService extends AbstractInputMethodService {
return false;
}
}
- if ((flags&InputMethod.SHOW_FORCED) != 0) {
- mShowInputForced = true;
- }
return true;
}
-
+
+ /**
+ * A utility method to call {{@link #onShowInputRequested(int, boolean)}} and update internal
+ * states depending on its result. Since {@link #onShowInputRequested(int, boolean)} is
+ * exposed to IME authors as an overridable public method without {@code @CallSuper}, we have
+ * to have this method to ensure that those internal states are always updated no matter how
+ * {@link #onShowInputRequested(int, boolean)} is overridden by the IME author.
+ * @param flags Provides additional information about the show request,
+ * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
+ * @param configChange This is true if we are re-showing due to a
+ * configuration change.
+ * @return Returns true to indicate that the window should be shown.
+ * @see #onShowInputRequested(int, boolean)
+ */
+ private boolean dispatchOnShowInputRequested(int flags, boolean configChange) {
+ final boolean result = onShowInputRequested(flags, configChange);
+ if (result) {
+ mShowInputFlags = flags;
+ } else {
+ mShowInputFlags = 0;
+ }
+ return result;
+ }
+
public void showWindow(boolean showInput) {
if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
+ " mShowInputRequested=" + mShowInputRequested
+ " mWindowAdded=" + mWindowAdded
+ " mWindowCreated=" + mWindowCreated
+ " mWindowVisible=" + mWindowVisible
- + " mInputStarted=" + mInputStarted);
-
+ + " mInputStarted=" + mInputStarted
+ + " mShowInputFlags=" + mShowInputFlags);
+
if (mInShowWindow) {
Log.w(TAG, "Re-entrance in to showWindow");
return;
@@ -2573,7 +2597,6 @@ public class InputMethodService extends AbstractInputMethodService {
p.println(" mShowInputRequested=" + mShowInputRequested
+ " mLastShowInputRequested=" + mLastShowInputRequested
- + " mShowInputForced=" + mShowInputForced
+ " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
p.println(" mCandidatesVisibility=" + mCandidatesVisibility
+ " mFullscreenApplied=" + mFullscreenApplied
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index f0673fffc0d8..b4523412aa83 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3021,7 +3021,6 @@ public class ConnectivityManager {
*
* @param networkCallback The {@link NetworkCallback} that the system will call as the
* system default network changes.
- * @hide
*/
public void registerDefaultNetworkCallback(NetworkCallback networkCallback) {
// This works because if the NetworkCapabilities are null,
diff --git a/core/java/android/net/ConnectivityMetricsEvent.aidl b/core/java/android/net/ConnectivityMetricsEvent.aidl
index da175614b588..a027d7c38140 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.aidl
+++ b/core/java/android/net/ConnectivityMetricsEvent.aidl
@@ -17,3 +17,4 @@
package android.net;
parcelable ConnectivityMetricsEvent;
+parcelable ConnectivityMetricsEvent.Reference;
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 098f1e6947a3..b5d67d38455d 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -78,4 +78,42 @@ public final class ConnectivityMetricsEvent implements Parcelable {
return String.format("ConnectivityMetricsEvent(%d, %d, %d)", timestamp,
componentTag, eventTag);
}
+
+ /** {@hide} */
+ public static class Reference implements Parcelable {
+
+ public long value;
+
+ public Reference(long ref) {
+ this.value = ref;
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Parcelable.Creator<Reference> CREATOR
+ = new Parcelable.Creator<Reference> (){
+ public Reference createFromParcel(Parcel source) {
+ return new Reference(source.readLong());
+ }
+
+ public Reference[] newArray(int size) {
+ return new Reference[size];
+ }
+ };
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(value);
+ }
+
+ public void readFromParcel(Parcel in) {
+ value = in.readLong();
+ }
+ }
}
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java
index 3ef805017f14..eafb8acb8aeb 100644
--- a/core/java/android/net/ConnectivityMetricsLogger.java
+++ b/core/java/android/net/ConnectivityMetricsLogger.java
@@ -15,6 +15,7 @@
*/
package android.net;
+import android.os.Bundle;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -28,14 +29,24 @@ public class ConnectivityMetricsLogger {
public static final String CONNECTIVITY_METRICS_LOGGER_SERVICE = "connectivity_metrics_logger";
// Component Tags
- public static final int COMPONENT_TAG_CONNECTIVITY = 1;
- public static final int COMPONENT_TAG_BLUETOOTH = 2;
- public static final int COMPONENT_TAG_WIFI = 3;
- public static final int COMPONENT_TAG_TELECOM = 4;
- public static final int COMPONENT_TAG_TELEPHONY = 5;
+ public static final int COMPONENT_TAG_CONNECTIVITY = 0;
+ public static final int COMPONENT_TAG_BLUETOOTH = 1;
+ public static final int COMPONENT_TAG_WIFI = 2;
+ public static final int COMPONENT_TAG_TELECOM = 3;
+ public static final int COMPONENT_TAG_TELEPHONY = 4;
+
+ public static final int NUMBER_OF_COMPONENTS = 5;
+
+ // Event Tag
+ public static final int TAG_SKIPPED_EVENTS = -1;
+
+ public static final String DATA_KEY_EVENTS_COUNT = "count";
private IConnectivityMetricsLogger mService;
+ private long mServiceUnblockedTimestampMillis = 0;
+ private int mNumSkippedEvents = 0;
+
public ConnectivityMetricsLogger() {
mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService(
CONNECTIVITY_METRICS_LOGGER_SERVICE));
@@ -46,12 +57,51 @@ public class ConnectivityMetricsLogger {
if (DBG) {
Log.d(TAG, "logEvent(" + componentTag + "," + eventTag + ") Service not ready");
}
- } else {
- try {
- mService.logEvent(new ConnectivityMetricsEvent(timestamp, componentTag, eventTag, data));
- } catch (RemoteException e) {
- Log.e(TAG, "Error logging event " + e.getMessage());
+ return;
+ }
+
+ if (mServiceUnblockedTimestampMillis > 0) {
+ if (System.currentTimeMillis() < mServiceUnblockedTimestampMillis) {
+ // Service is throttling events.
+ // Don't send new events because they will be dropped.
+ mNumSkippedEvents++;
+ return;
+ }
+ }
+
+ ConnectivityMetricsEvent skippedEventsEvent = null;
+ if (mNumSkippedEvents > 0) {
+ // Log number of skipped events
+ Bundle b = new Bundle();
+ b.putInt(DATA_KEY_EVENTS_COUNT, mNumSkippedEvents);
+ skippedEventsEvent = new ConnectivityMetricsEvent(mServiceUnblockedTimestampMillis,
+ componentTag, TAG_SKIPPED_EVENTS, b);
+
+ mServiceUnblockedTimestampMillis = 0;
+ }
+
+ ConnectivityMetricsEvent event = new ConnectivityMetricsEvent(timestamp, componentTag,
+ eventTag, data);
+
+ try {
+ long result;
+ if (skippedEventsEvent == null) {
+ result = mService.logEvent(event);
+ } else {
+ result = mService.logEvents(new ConnectivityMetricsEvent[]
+ {skippedEventsEvent, event});
+ }
+
+ if (result == 0) {
+ mNumSkippedEvents = 0;
+ } else {
+ mNumSkippedEvents++;
+ if (result > 0) { // events are throttled
+ mServiceUnblockedTimestampMillis = result;
+ }
}
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error logging event " + e.getMessage());
}
}
}
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
deleted file mode 100644
index 7acf3f556595..000000000000
--- a/core/java/android/net/DnsPinger.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.util.Protocol;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketTimeoutException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Performs a simple DNS "ping" by sending a "server status" query packet to the
- * DNS server. As long as the server replies, we consider it a success.
- * <p>
- * We do not use a simple hostname lookup because that could be cached and the
- * API may not differentiate between a time out and a failure lookup (which we
- * really care about).
- * <p>
- *
- * @hide
- */
-public final class DnsPinger extends Handler {
- private static final boolean DBG = false;
-
- private static final int RECEIVE_POLL_INTERVAL_MS = 200;
- private static final int DNS_PORT = 53;
-
- /** Short socket timeout so we don't block one any 'receive' call */
- private static final int SOCKET_TIMEOUT_MS = 1;
-
- /** Used to generate IDs */
- private static final Random sRandom = new Random();
- private static final AtomicInteger sCounter = new AtomicInteger();
-
- private ConnectivityManager mConnectivityManager = null;
- private final Context mContext;
- private final int mConnectionType;
- private final Handler mTarget;
- private final ArrayList<InetAddress> mDefaultDns;
- private String TAG;
-
- //Invalidates old dns requests upon a cancel
- private AtomicInteger mCurrentToken = new AtomicInteger();
-
- private static final int BASE = Protocol.BASE_DNS_PINGER;
-
- /**
- * Async response packet for dns pings.
- * arg1 is the ID of the ping, also returned by {@link #pingDnsAsync(InetAddress, int, int)}
- * arg2 is the delay, or is negative on error.
- */
- public static final int DNS_PING_RESULT = BASE;
- /** An error code for a {@link #DNS_PING_RESULT} packet */
- public static final int TIMEOUT = -1;
- /** An error code for a {@link #DNS_PING_RESULT} packet */
- public static final int SOCKET_EXCEPTION = -2;
-
- /**
- * Send a new ping via a socket. arg1 is ID, arg2 is timeout, obj is InetAddress to ping
- */
- private static final int ACTION_PING_DNS = BASE + 1;
- private static final int ACTION_LISTEN_FOR_RESPONSE = BASE + 2;
- private static final int ACTION_CANCEL_ALL_PINGS = BASE + 3;
-
- private List<ActivePing> mActivePings = new ArrayList<ActivePing>();
- private int mEventCounter;
-
- private class ActivePing {
- DatagramSocket socket;
- int internalId;
- short packetId;
- int timeout;
- Integer result;
- long start = SystemClock.elapsedRealtime();
- }
-
- /* Message argument for ACTION_PING_DNS */
- private class DnsArg {
- InetAddress dns;
- int seq;
-
- DnsArg(InetAddress d, int s) {
- dns = d;
- seq = s;
- }
- }
-
- public DnsPinger(Context context, String TAG, Looper looper,
- Handler target, int connectionType) {
- super(looper);
- this.TAG = TAG;
- mContext = context;
- mTarget = target;
- mConnectionType = connectionType;
- if (!ConnectivityManager.isNetworkTypeValid(connectionType)) {
- throw new IllegalArgumentException("Invalid connectionType in constructor: "
- + connectionType);
- }
- mDefaultDns = new ArrayList<InetAddress>();
- mDefaultDns.add(getDefaultDns());
- mEventCounter = 0;
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case ACTION_PING_DNS:
- DnsArg dnsArg = (DnsArg) msg.obj;
- if (dnsArg.seq != mCurrentToken.get()) {
- break;
- }
- try {
- ActivePing newActivePing = new ActivePing();
- InetAddress dnsAddress = dnsArg.dns;
- newActivePing.internalId = msg.arg1;
- newActivePing.timeout = msg.arg2;
- newActivePing.socket = new DatagramSocket();
- // Set some socket properties
- newActivePing.socket.setSoTimeout(SOCKET_TIMEOUT_MS);
-
- // Try to bind but continue ping if bind fails
- try {
- newActivePing.socket.setNetworkInterface(NetworkInterface.getByName(
- getCurrentLinkProperties().getInterfaceName()));
- } catch (Exception e) {
- loge("sendDnsPing::Error binding to socket " + e);
- }
-
- newActivePing.packetId = (short) sRandom.nextInt();
- byte[] buf = mDnsQuery.clone();
- buf[0] = (byte) (newActivePing.packetId >> 8);
- buf[1] = (byte) newActivePing.packetId;
-
- // Send the DNS query
- DatagramPacket packet = new DatagramPacket(buf,
- buf.length, dnsAddress, DNS_PORT);
- if (DBG) {
- log("Sending a ping " + newActivePing.internalId +
- " to " + dnsAddress.getHostAddress()
- + " with packetId " + newActivePing.packetId + ".");
- }
-
- newActivePing.socket.send(packet);
- mActivePings.add(newActivePing);
- mEventCounter++;
- sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
- RECEIVE_POLL_INTERVAL_MS);
- } catch (IOException e) {
- sendResponse(msg.arg1, -9999, SOCKET_EXCEPTION);
- }
- break;
- case ACTION_LISTEN_FOR_RESPONSE:
- if (msg.arg1 != mEventCounter) {
- break;
- }
- for (ActivePing curPing : mActivePings) {
- try {
- /** Each socket will block for {@link #SOCKET_TIMEOUT_MS} in receive() */
- byte[] responseBuf = new byte[2];
- DatagramPacket replyPacket = new DatagramPacket(responseBuf, 2);
- curPing.socket.receive(replyPacket);
- // Check that ID field matches (we're throwing out the rest of the packet)
- if (responseBuf[0] == (byte) (curPing.packetId >> 8) &&
- responseBuf[1] == (byte) curPing.packetId) {
- curPing.result =
- (int) (SystemClock.elapsedRealtime() - curPing.start);
- } else {
- if (DBG) {
- log("response ID didn't match, ignoring packet");
- }
- }
- } catch (SocketTimeoutException e) {
- // A timeout here doesn't mean anything - squelsh this exception
- } catch (Exception e) {
- if (DBG) {
- log("DnsPinger.pingDns got socket exception: " + e);
- }
- curPing.result = SOCKET_EXCEPTION;
- }
- }
- Iterator<ActivePing> iter = mActivePings.iterator();
- while (iter.hasNext()) {
- ActivePing curPing = iter.next();
- if (curPing.result != null) {
- sendResponse(curPing.internalId, curPing.packetId, curPing.result);
- curPing.socket.close();
- iter.remove();
- } else if (SystemClock.elapsedRealtime() >
- curPing.start + curPing.timeout) {
- sendResponse(curPing.internalId, curPing.packetId, TIMEOUT);
- curPing.socket.close();
- iter.remove();
- }
- }
- if (!mActivePings.isEmpty()) {
- sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
- RECEIVE_POLL_INTERVAL_MS);
- }
- break;
- case ACTION_CANCEL_ALL_PINGS:
- for (ActivePing activePing : mActivePings)
- activePing.socket.close();
- mActivePings.clear();
- break;
- }
- }
-
- /**
- * Returns a list of DNS addresses, coming from either the link properties of the
- * specified connection or the default system DNS if the link properties has no dnses.
- * @return a non-empty non-null list
- */
- public List<InetAddress> getDnsList() {
- LinkProperties curLinkProps = getCurrentLinkProperties();
- if (curLinkProps == null) {
- loge("getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
- return mDefaultDns;
- }
-
- Collection<InetAddress> dnses = curLinkProps.getDnsServers();
- if (dnses == null || dnses.size() == 0) {
- loge("getDns::LinkProps has null dns - returning default");
- return mDefaultDns;
- }
-
- return new ArrayList<InetAddress>(dnses);
- }
-
- /**
- * Send a ping. The response will come via a {@link #DNS_PING_RESULT} to the handler
- * specified at creation.
- * @param dns address of dns server to ping
- * @param timeout timeout for ping
- * @return an ID field, which will also be included in the {@link #DNS_PING_RESULT} message.
- */
- public int pingDnsAsync(InetAddress dns, int timeout, int delay) {
- int id = sCounter.incrementAndGet();
- sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout,
- new DnsArg(dns, mCurrentToken.get())), delay);
- return id;
- }
-
- public void cancelPings() {
- mCurrentToken.incrementAndGet();
- obtainMessage(ACTION_CANCEL_ALL_PINGS).sendToTarget();
- }
-
- private void sendResponse(int internalId, int externalId, int responseVal) {
- if(DBG) {
- log("Responding to packet " + internalId +
- " externalId " + externalId +
- " and val " + responseVal);
- }
- mTarget.sendMessage(obtainMessage(DNS_PING_RESULT, internalId, responseVal));
- }
-
- private LinkProperties getCurrentLinkProperties() {
- if (mConnectivityManager == null) {
- mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- }
-
- return mConnectivityManager.getLinkProperties(mConnectionType);
- }
-
- private InetAddress getDefaultDns() {
- String dns = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.DEFAULT_DNS_SERVER);
- if (dns == null || dns.length() == 0) {
- dns = mContext.getResources().getString(
- com.android.internal.R.string.config_default_dns_server);
- }
- try {
- return NetworkUtils.numericToInetAddress(dns);
- } catch (IllegalArgumentException e) {
- loge("getDefaultDns::malformed default dns address");
- return null;
- }
- }
-
- private static final byte[] mDnsQuery = new byte[] {
- 0, 0, // [0-1] is for ID (will set each time)
- 1, 0, // [2-3] are flags. Set byte[2] = 1 for recursion desired (RD) on. Currently on.
- 0, 1, // [4-5] bytes are for number of queries (QCOUNT)
- 0, 0, // [6-7] unused count field for dns response packets
- 0, 0, // [8-9] unused count field for dns response packets
- 0, 0, // [10-11] unused count field for dns response packets
- 3, 'w', 'w', 'w',
- 6, 'g', 'o', 'o', 'g', 'l', 'e',
- 3, 'c', 'o', 'm',
- 0, // null terminator of address (also called empty TLD)
- 0, 1, // QTYPE, set to 1 = A (host address)
- 0, 1 // QCLASS, set to 1 = IN (internet)
- };
-
- private void log(String s) {
- Log.d(TAG, s);
- }
-
- private void loge(String s) {
- Log.e(TAG, s);
- }
-}
diff --git a/core/java/android/net/IConnectivityMetricsLogger.aidl b/core/java/android/net/IConnectivityMetricsLogger.aidl
index 27786712a5c5..a83a01935253 100644
--- a/core/java/android/net/IConnectivityMetricsLogger.aidl
+++ b/core/java/android/net/IConnectivityMetricsLogger.aidl
@@ -16,15 +16,28 @@
package android.net;
+import android.app.PendingIntent;
import android.net.ConnectivityMetricsEvent;
-import android.net.IConnectivityMetricsLoggerSubscriber;
/** {@hide} */
interface IConnectivityMetricsLogger {
- void logEvent(in ConnectivityMetricsEvent event);
- void logEvents(in ConnectivityMetricsEvent[] events);
+ /**
+ * @return 0 on success
+ * <0 if error happened
+ * >0 timestamp after which new events will be accepted
+ */
+ long logEvent(in ConnectivityMetricsEvent event);
+ long logEvents(in ConnectivityMetricsEvent[] events);
- boolean subscribe(in IConnectivityMetricsLoggerSubscriber subscriber);
- void unsubscribe(in IConnectivityMetricsLoggerSubscriber subscriber);
+ /**
+ * @param reference of the last event previously returned. The function will return
+ * events following it.
+ * If 0 then all events will be returned.
+ * After the function call it will contain reference of the last event.
+ */
+ ConnectivityMetricsEvent[] getEvents(inout ConnectivityMetricsEvent.Reference reference);
+
+ boolean register(in PendingIntent newEventsIntent);
+ void unregister(in PendingIntent newEventsIntent);
}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index e555fa412a5b..29291ca90467 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -19,11 +19,9 @@ package android.net;
import android.Manifest;
import android.Manifest.permission;
import android.annotation.Nullable;
-import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
@@ -69,12 +67,32 @@ public final class NetworkScorerAppManager {
*/
public final String mConfigurationActivityClassName;
+ /**
+ * Optional class name of the scoring service we can bind to. Null if none is set.
+ */
+ public final String mScoringServiceClassName;
+
public NetworkScorerAppData(String packageName, int packageUid, CharSequence scorerName,
- @Nullable String configurationActivityClassName) {
+ @Nullable String configurationActivityClassName,
+ @Nullable String scoringServiceClassName) {
mScorerName = scorerName;
mPackageName = packageName;
mPackageUid = packageUid;
mConfigurationActivityClassName = configurationActivityClassName;
+ mScoringServiceClassName = scoringServiceClassName;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("NetworkScorerAppData{");
+ sb.append("mPackageName='").append(mPackageName).append('\'');
+ sb.append(", mPackageUid=").append(mPackageUid);
+ sb.append(", mScorerName=").append(mScorerName);
+ sb.append(", mConfigurationActivityClassName='").append(mConfigurationActivityClassName)
+ .append('\'');
+ sb.append(", mScoringServiceClassName='").append(mScoringServiceClassName).append('\'');
+ sb.append('}');
+ return sb.toString();
}
}
@@ -128,18 +146,27 @@ public final class NetworkScorerAppManager {
Intent intent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE);
intent.setPackage(receiverInfo.packageName);
List<ResolveInfo> configActivities = pm.queryIntentActivities(intent, 0 /* flags */);
- if (!configActivities.isEmpty()) {
+ if (configActivities != null && !configActivities.isEmpty()) {
ActivityInfo activityInfo = configActivities.get(0).activityInfo;
if (activityInfo != null) {
configurationActivityClassName = activityInfo.name;
}
}
+ // Find the scoring service class we can bind to, if any.
+ String scoringServiceClassName = null;
+ Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
+ serviceIntent.setPackage(receiverInfo.packageName);
+ ResolveInfo resolveServiceInfo = pm.resolveService(serviceIntent, 0 /* flags */);
+ if (resolveServiceInfo != null && resolveServiceInfo.serviceInfo != null) {
+ scoringServiceClassName = resolveServiceInfo.serviceInfo.name;
+ }
+
// NOTE: loadLabel will attempt to load the receiver's label and fall back to the
// app label if none is present.
scorers.add(new NetworkScorerAppData(receiverInfo.packageName,
receiverInfo.applicationInfo.uid, receiverInfo.loadLabel(pm),
- configurationActivityClassName));
+ configurationActivityClassName, scoringServiceClassName));
}
return scorers;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8e2dd6b85c00..c4528372987f 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -448,19 +448,41 @@ public abstract class BatteryStats implements Parcelable {
public abstract Timer getForegroundActivityTimer();
public abstract Timer getBluetoothScanTimer();
- // Time this uid has any processes in the top state.
+ // Note: the following times are disjoint. They can be added together to find the
+ // total time a uid has had any processes running at all.
+
+ /**
+ * Time this uid has any processes in the top state (or above such as persistent).
+ */
public static final int PROCESS_STATE_TOP = 0;
- // Time this uid has any process with a started out bound foreground service.
+ /**
+ * Time this uid has any process with a started out bound foreground service, but
+ * none in the "top" state.
+ */
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 1;
- // Time this uid has any process that is top while the device is sleeping.
+ /**
+ * Time this uid has any process that is top while the device is sleeping, but none
+ * in the "foreground service" or better state.
+ */
public static final int PROCESS_STATE_TOP_SLEEPING = 2;
- // Time this uid has any process in an active foreground state.
+ /**
+ * Time this uid has any process in an active foreground state, but none in the
+ * "top sleeping" or better state.
+ */
public static final int PROCESS_STATE_FOREGROUND = 3;
- // Time this uid has any process in an active background state.
+ /**
+ * Time this uid has any process in an active background state, but none in the
+ * "foreground" or better state.
+ */
public static final int PROCESS_STATE_BACKGROUND = 4;
- // Time this uid has any processes running at all.
+ /**
+ * Time this uid has any processes that are sitting around cached, not in one of the
+ * other active states.
+ */
public static final int PROCESS_STATE_CACHED = 5;
- // Total number of process states we track.
+ /**
+ * Total number of process states we track.
+ */
public static final int NUM_PROCESS_STATE = 6;
static final String[] PROCESS_STATE_NAMES = {
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 878b7a0e8e10..3c7c962eaa12 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -231,6 +231,18 @@ public class Handler {
mAsynchronous = async;
}
+ /** {@hide} */
+ public String getTraceName(Message message) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getName()).append(": ");
+ if (message.callback != null) {
+ sb.append(message.callback.getClass().getName());
+ } else {
+ sb.append("#").append(message.what);
+ }
+ return sb.toString();
+ }
+
/**
* Returns a string representing the name of the specified message.
* The default implementation will either return the class name of the
@@ -739,8 +751,8 @@ public class Handler {
message.callback.run();
}
- final MessageQueue mQueue;
final Looper mLooper;
+ final MessageQueue mQueue;
final Callback mCallback;
final boolean mAsynchronous;
IMessenger mMessenger;
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 24a6cdf83b7a..68b0a9fb2969 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -328,11 +328,6 @@ interface INetworkManagementService
*/
void setDnsServersForNetwork(int netId, in String[] servers, String domains);
- /**
- * Flush the DNS cache associated with the specified network.
- */
- void flushNetworkDnsCache(int netId);
-
void setFirewallEnabled(boolean enabled);
boolean isFirewallEnabled();
void setFirewallInterfaceRule(String iface, boolean allow);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 34c880f60520..b58ff1fd4755 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -72,6 +72,7 @@ public final class Looper {
final Thread mThread;
private Printer mLogging;
+ private long mTraceTag;
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
@@ -139,13 +140,23 @@ public final class Looper {
}
// This must be in a local variable, in case a UI event sets the logger
- Printer logging = me.mLogging;
+ final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
- msg.target.dispatchMessage(msg);
+ final long traceTag = me.mTraceTag;
+ if (traceTag != 0) {
+ Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
+ }
+ try {
+ msg.target.dispatchMessage(msg);
+ } finally {
+ if (traceTag != 0) {
+ Trace.traceEnd(traceTag);
+ }
+ }
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
@@ -208,6 +219,11 @@ public final class Looper {
mLogging = printer;
}
+ /** {@hide} */
+ public void setTraceTag(long traceTag) {
+ mTraceTag = traceTag;
+ }
+
/**
* Quits the looper.
* <p>
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a0a16f1a8930..92edc62617cb 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -221,7 +221,7 @@ public final class PowerManager {
/**
* Wake lock level: Enables Sustained Performance Mode.
* <p>
- * This is used by Gaming and VR applications to ensure the device provides
+ * This is used by Gaming and VR applications to ensure the device
* will provide consistent performance over a large amount of time.
* </p>
*/
@@ -1031,6 +1031,16 @@ public final class PowerManager {
}
/**
+ * Returns True if the device supports Sustained Performance Mode.
+ * Applications Should check if the device supports this mode, before
+ * using {@link #SUSTAINED_PERFORMANCE_WAKE_LOCK}.
+ */
+ public boolean isSustainedPerformanceModeSupported() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_sustainedPerformanceModeSupported);
+ }
+
+ /**
* Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
* This broadcast is only sent to registered receivers.
*/
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 720d3f7b860a..f2e316cf214f 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1178,23 +1178,7 @@ public class StorageManager {
/** {@hide} */
public static File maybeTranslateEmulatedPathToInternal(File path) {
- final IMountService mountService = IMountService.Stub.asInterface(
- ServiceManager.getService("mount"));
- try {
- final VolumeInfo[] vols = mountService.getVolumes(0);
- for (VolumeInfo vol : vols) {
- if ((vol.getType() == VolumeInfo.TYPE_EMULATED
- || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
- final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
- vol.getInternalPath(), path);
- if (internalPath != null && internalPath.exists()) {
- return internalPath;
- }
- }
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ // Disabled now that FUSE has been replaced by sdcardfs
return path;
}
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index d41bc070d6c1..b1cad0538d31 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1184,10 +1184,9 @@ public class Preference implements Comparable<Preference> {
/**
* Called when the Preference hierarchy has been attached to the
- * {@link PreferenceActivity} or {@link PreferenceFragment}. This can
- * also be called when this Preference has been attached to a group
- * that was already attached to the {@link PreferenceActivity} or
- * {@link PreferenceFragment}.
+ * {@link PreferenceActivity}. This can also be called when this
+ * Preference has been attached to a group that was already attached
+ * to the {@link PreferenceActivity}.
*/
protected void onAttachedToActivity() {
// At this point, the hierarchy that this preference is in is connected
@@ -1195,16 +1194,6 @@ public class Preference implements Comparable<Preference> {
registerDependency();
}
- /**
- * Called when the Preference hierarchy has been detached from the
- * {@link PreferenceActivity} or {@link PreferenceFragment}. This can
- * also be called when this Preference has been removed from a group
- * that was already attached to the {@link PreferenceActivity} or
- * {@link PreferenceFragment}.
- */
- protected void onDetachedFromActivity() {
- }
-
private void registerDependency() {
if (TextUtils.isEmpty(mDependencyKey)) return;
diff --git a/core/java/android/preference/PreferenceGroup.java b/core/java/android/preference/PreferenceGroup.java
index 13c36614729e..f17506b98a2b 100644
--- a/core/java/android/preference/PreferenceGroup.java
+++ b/core/java/android/preference/PreferenceGroup.java
@@ -186,11 +186,7 @@ public abstract class PreferenceGroup extends Preference implements GenericInfla
private boolean removePreferenceInt(Preference preference) {
synchronized(this) {
preference.onPrepareForRemoval();
- boolean success = mPreferenceList.remove(preference);
- if (mAttachedToActivity) {
- preference.onDetachedFromActivity();
- }
- return success;
+ return mPreferenceList.remove(preference);
}
}
@@ -266,7 +262,7 @@ public abstract class PreferenceGroup extends Preference implements GenericInfla
protected boolean isOnSameScreenAsChildren() {
return true;
}
-
+
@Override
protected void onAttachedToActivity() {
super.onAttachedToActivity();
@@ -283,17 +279,11 @@ public abstract class PreferenceGroup extends Preference implements GenericInfla
}
@Override
- protected void onDetachedFromActivity() {
- super.onDetachedFromActivity();
-
+ protected void onPrepareForRemoval() {
+ super.onPrepareForRemoval();
+
// We won't be attached to the activity anymore
mAttachedToActivity = false;
-
- // Dispatch to all contained preferences
- final int preferenceCount = getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- getPreference(i).onDetachedFromActivity();
- }
}
@Override
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index 73174e310e11..1a6b06f33199 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -519,9 +519,6 @@ public class PreferenceManager {
*/
boolean setPreferences(PreferenceScreen preferenceScreen) {
if (preferenceScreen != mPreferenceScreen) {
- if (mPreferenceScreen != null) {
- mPreferenceScreen.onDetachedFromActivity();
- }
mPreferenceScreen = preferenceScreen;
return true;
}
@@ -830,11 +827,7 @@ public class PreferenceManager {
*/
void dispatchActivityDestroy() {
List<OnActivityDestroyListener> list = null;
-
- if (mPreferenceScreen != null) {
- mPreferenceScreen.onDetachedFromActivity();
- mPreferenceScreen = null;
- }
+
synchronized (this) {
if (mActivityDestroyListeners != null) {
list = new ArrayList<OnActivityDestroyListener>(mActivityDestroyListeners);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 69dd9e5abe69..2a3c3fe2e5c1 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1569,9 +1569,8 @@ public final class Settings {
* @return true if the calling app can draw on top of other apps, false otherwise.
*/
public static boolean canDrawOverlays(Context context) {
- int uid = Binder.getCallingUid();
- return Settings.isCallingPackageAllowedToDrawOverlays(context, uid, Settings
- .getPackageNameForUid(context, uid), false);
+ return Settings.isCallingPackageAllowedToDrawOverlays(context, Process.myUid(),
+ context.getOpPackageName(), false);
}
/**
@@ -3885,9 +3884,8 @@ public final class Settings {
* @return true if the calling app can write to system settings, false otherwise
*/
public static boolean canWrite(Context context) {
- int uid = Binder.getCallingUid();
- return isCallingPackageAllowedToWriteSettings(context, uid, getPackageNameForUid(
- context, uid), false);
+ return isCallingPackageAllowedToWriteSettings(context, Process.myUid(),
+ context.getOpPackageName(), false);
}
}
@@ -8308,6 +8306,16 @@ public final class Settings {
public static final String BOOT_COUNT = "boot_count";
/**
+ * Whether the safe boot is disallowed.
+ *
+ * <p>This setting should have the identical value as the corresponding user restriction.
+ * The purpose of the setting is to make the restriction available in early boot stages
+ * before the user restrictions are loaded.
+ * @hide
+ */
+ public static final String SAFE_BOOT_DISALLOWED = "safe_boot_disallowed";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
new file mode 100644
index 000000000000..62ecab3583cd
--- /dev/null
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.vr;
+
+import android.service.vr.IVrStateCallbacks;
+
+/** @hide */
+interface IVrManager {
+
+ /**
+ * Add a callback to be notified when VR mode state changes.
+ *
+ * @param cb the callback instance to add.
+ */
+ void registerListener(in IVrStateCallbacks cb);
+
+ /**
+ * Remove the callack from the current set of registered callbacks.
+ *
+ * @param cb the callback to remove.
+ */
+ void unregisterListener(in IVrStateCallbacks cb);
+
+ /**
+ * Return current VR mode state.
+ *
+ * @return {@code true} if VR mode is enabled.
+ */
+ boolean getVrModeState();
+
+}
+
diff --git a/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl b/core/java/android/service/vr/IVrStateCallbacks.aidl
index a2c62cdaee97..c4fdcd071fe5 100644
--- a/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
+++ b/core/java/android/service/vr/IVrStateCallbacks.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-package android.net;
+package android.service.vr;
-import android.net.ConnectivityMetricsEvent;
+/** @hide */
+oneway interface IVrStateCallbacks {
-/** {@hide} */
-oneway interface IConnectivityMetricsLoggerSubscriber {
+ void onVrStateChanged(in boolean enabled);
- void onEvents(in ConnectivityMetricsEvent[] events);
}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 328fe99a7f93..7f0021d729d0 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -183,8 +183,10 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
if (includepad) {
spacing = metrics.bottom - metrics.top;
+ mDesc = metrics.bottom;
} else {
spacing = metrics.descent - metrics.ascent;
+ mDesc = metrics.descent;
}
mBottom = spacing;
@@ -208,8 +210,6 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
mTopPadding = metrics.top - metrics.ascent;
mBottomPadding = metrics.bottom - metrics.descent;
}
-
- mDesc = spacing + mBottomPadding + (includepad ? metrics.top : metrics.ascent);
}
/**
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6a33579153bc..94ce57ac7cb9 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -1132,22 +1132,12 @@ public class StaticLayout extends Layout {
@Override
public int getLineTop(int line) {
- int top = mLines[mColumns * line + TOP];
- if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount &&
- line != mLineCount) {
- top += getBottomPadding();
- }
- return top;
+ return mLines[mColumns * line + TOP];
}
@Override
public int getLineDescent(int line) {
- int descent = mLines[mColumns * line + DESCENT];
- if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount - 1 && // -1 intended
- line != mLineCount) {
- descent += getBottomPadding();
- }
- return descent;
+ return mLines[mColumns * line + DESCENT];
}
@Override
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 4888877cb28b..86318e91b885 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -101,6 +101,15 @@ public class ContextThemeWrapper extends ContextWrapper {
mOverrideConfiguration = new Configuration(overrideConfiguration);
}
+ /**
+ * Used by ActivityThread to apply the overridden configuration to onConfigurationChange
+ * callbacks.
+ * @hide
+ */
+ public Configuration getOverrideConfiguration() {
+ return mOverrideConfiguration;
+ }
+
@Override
public AssetManager getAssets() {
// Ensure we're returning assets with the correct configuration.
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index e0c6770ecb38..636384c616e0 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1870,6 +1870,11 @@ public class KeyEvent extends InputEvent implements Parcelable {
return keyCode == KeyEvent.KEYCODE_META_LEFT || keyCode == KeyEvent.KEYCODE_META_RIGHT;
}
+ /** @hide */
+ public static final boolean isAltKey(int keyCode) {
+ return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT;
+ }
+
/** {@inheritDoc} */
@Override
public final int getDeviceId() {
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index cff9d8e93c98..37da8695a1ad 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -22,7 +22,6 @@ import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.RemoteViews;
-import android.widget.TextView;
import java.util.ArrayList;
@@ -37,7 +36,7 @@ public class NotificationHeaderView extends ViewGroup {
private final int mChildMinWidth;
private final int mContentEndMargin;
private View mAppName;
- private View mSubTextView;
+ private View mHeaderText;
private OnClickListener mExpandClickListener;
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
private ImageView mExpandButton;
@@ -73,11 +72,10 @@ public class NotificationHeaderView extends ViewGroup {
protected void onFinishInflate() {
super.onFinishInflate();
mAppName = findViewById(com.android.internal.R.id.app_name_text);
- mSubTextView = findViewById(com.android.internal.R.id.header_sub_text);
+ mHeaderText = findViewById(com.android.internal.R.id.header_text);
mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button);
mIcon = findViewById(com.android.internal.R.id.icon);
mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
- mInfo = findViewById(com.android.internal.R.id.header_content_info);
}
@Override
@@ -105,15 +103,7 @@ public class NotificationHeaderView extends ViewGroup {
}
if (totalWidth > givenWidth) {
int overFlow = totalWidth - givenWidth;
- // We are overflowing, lets shrink the info first
- final int infoWidth = mInfo.getMeasuredWidth();
- if (mInfo.getVisibility() != GONE && infoWidth > mChildMinWidth) {
- int newSize = infoWidth - Math.min(infoWidth - mChildMinWidth, overFlow);
- int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
- mInfo.measure(childWidthSpec, wrapContentHeightSpec);
- overFlow -= infoWidth - newSize;
- }
- // still overflowing, lets shrink the app name now
+ // We are overflowing, lets shrink the app name first
final int appWidth = mAppName.getMeasuredWidth();
if (overFlow > 0 && mAppName.getVisibility() != GONE && appWidth > mChildMinWidth) {
int newSize = appWidth - Math.min(appWidth - mChildMinWidth, overFlow);
@@ -121,13 +111,13 @@ public class NotificationHeaderView extends ViewGroup {
mAppName.measure(childWidthSpec, wrapContentHeightSpec);
overFlow -= appWidth - newSize;
}
- // still overflowing, finaly we shrink the subtext
- if (overFlow > 0 && mSubTextView.getVisibility() != GONE) {
+ // still overflowing, finaly we shrink the header text
+ if (overFlow > 0 && mHeaderText.getVisibility() != GONE) {
// we're still too big
- final int subTextWidth = mSubTextView.getMeasuredWidth();
- int newSize = Math.max(0, subTextWidth - overFlow);
+ final int textWidth = mHeaderText.getMeasuredWidth();
+ int newSize = Math.max(0, textWidth - overFlow);
int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
- mSubTextView.measure(childWidthSpec, wrapContentHeightSpec);
+ mHeaderText.measure(childWidthSpec, wrapContentHeightSpec);
}
}
setMeasuredDimension(givenWidth, givenHeight);
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 4ffb3d3b64bf..ab4cbcf21bed 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -307,18 +307,22 @@ public class RenderNode {
*
* Deep copies the data into native to simplify reference ownership.
*/
- public boolean setOutline(Outline outline) {
+ public boolean setOutline(@Nullable Outline outline) {
if (outline == null) {
return nSetOutlineNone(mNativeRenderNode);
- } else if (outline.isEmpty()) {
- return nSetOutlineEmpty(mNativeRenderNode);
- } else if (outline.mRect != null) {
- return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
- outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
- } else if (outline.mPath != null) {
- return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
- outline.mAlpha);
}
+
+ switch(outline.mMode) {
+ case Outline.MODE_EMPTY:
+ return nSetOutlineEmpty(mNativeRenderNode);
+ case Outline.MODE_ROUND_RECT:
+ return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
+ outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
+ case Outline.MODE_CONVEX_PATH:
+ return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
+ outline.mAlpha);
+ }
+
throw new IllegalArgumentException("Unrecognized outline?");
}
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 37e400014781..7cd161c17cd9 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -145,13 +145,6 @@ public class ScaleGestureDetector {
private int mSpanSlop;
private int mMinSpan;
- // Bounds for recently seen values
- private float mTouchUpper;
- private float mTouchLower;
- private float mTouchHistoryLastAccepted;
- private int mTouchHistoryDirection;
- private long mTouchHistoryLastAcceptedTime;
- private int mTouchMinMajor;
private final Handler mHandler;
private float mAnchoredScaleStartX;
@@ -207,8 +200,6 @@ public class ScaleGestureDetector {
mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
final Resources res = context.getResources();
- mTouchMinMajor = res.getDimensionPixelSize(
- com.android.internal.R.dimen.config_minScalingTouchMajor);
mMinSpan = res.getDimensionPixelSize(com.android.internal.R.dimen.config_minScalingSpan);
mHandler = handler;
// Quick scale is enabled by default after JB_MR2
@@ -223,77 +214,6 @@ public class ScaleGestureDetector {
}
/**
- * The touchMajor/touchMinor elements of a MotionEvent can flutter/jitter on
- * some hardware/driver combos. Smooth it out to get kinder, gentler behavior.
- * @param ev MotionEvent to add to the ongoing history
- */
- private void addTouchHistory(MotionEvent ev) {
- final long currentTime = SystemClock.uptimeMillis();
- final int count = ev.getPointerCount();
- boolean accept = currentTime - mTouchHistoryLastAcceptedTime >= TOUCH_STABILIZE_TIME;
- float total = 0;
- int sampleCount = 0;
- for (int i = 0; i < count; i++) {
- final boolean hasLastAccepted = !Float.isNaN(mTouchHistoryLastAccepted);
- final int historySize = ev.getHistorySize();
- final int pointerSampleCount = historySize + 1;
- for (int h = 0; h < pointerSampleCount; h++) {
- float major;
- if (h < historySize) {
- major = ev.getHistoricalTouchMajor(i, h);
- } else {
- major = ev.getTouchMajor(i);
- }
- if (major < mTouchMinMajor) major = mTouchMinMajor;
- total += major;
-
- if (Float.isNaN(mTouchUpper) || major > mTouchUpper) {
- mTouchUpper = major;
- }
- if (Float.isNaN(mTouchLower) || major < mTouchLower) {
- mTouchLower = major;
- }
-
- if (hasLastAccepted) {
- final int directionSig = (int) Math.signum(major - mTouchHistoryLastAccepted);
- if (directionSig != mTouchHistoryDirection ||
- (directionSig == 0 && mTouchHistoryDirection == 0)) {
- mTouchHistoryDirection = directionSig;
- final long time = h < historySize ? ev.getHistoricalEventTime(h)
- : ev.getEventTime();
- mTouchHistoryLastAcceptedTime = time;
- accept = false;
- }
- }
- }
- sampleCount += pointerSampleCount;
- }
-
- final float avg = total / sampleCount;
-
- if (accept) {
- float newAccepted = (mTouchUpper + mTouchLower + avg) / 3;
- mTouchUpper = (mTouchUpper + newAccepted) / 2;
- mTouchLower = (mTouchLower + newAccepted) / 2;
- mTouchHistoryLastAccepted = newAccepted;
- mTouchHistoryDirection = 0;
- mTouchHistoryLastAcceptedTime = ev.getEventTime();
- }
- }
-
- /**
- * Clear all touch history tracking. Useful in ACTION_CANCEL or ACTION_UP.
- * @see #addTouchHistory(MotionEvent)
- */
- private void clearTouchHistory() {
- mTouchUpper = Float.NaN;
- mTouchLower = Float.NaN;
- mTouchHistoryLastAccepted = Float.NaN;
- mTouchHistoryDirection = 0;
- mTouchHistoryLastAcceptedTime = 0;
- }
-
- /**
* Accepts MotionEvents and dispatches events to a {@link OnScaleGestureListener}
* when appropriate.
*
@@ -344,7 +264,6 @@ public class ScaleGestureDetector {
}
if (streamComplete) {
- clearTouchHistory();
return true;
}
}
@@ -391,17 +310,14 @@ public class ScaleGestureDetector {
focusY = sumY / div;
}
- addTouchHistory(event);
-
// Determine average deviation from focal point
float devSumX = 0, devSumY = 0;
for (int i = 0; i < count; i++) {
if (skipIndex == i) continue;
// Convert the resulting diameter into a radius.
- final float touchSize = mTouchHistoryLastAccepted / 2;
- devSumX += Math.abs(event.getX(i) - focusX) + touchSize;
- devSumY += Math.abs(event.getY(i) - focusY) + touchSize;
+ devSumX += Math.abs(event.getX(i) - focusX);
+ devSumY += Math.abs(event.getY(i) - focusY);
}
final float devX = devSumX / div;
final float devY = devSumY / div;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 784164d243f1..b95d830ca9f2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2434,6 +2434,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* 11111111 PFLAG3_POINTER_ICON_MASK
* 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
* 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
+ * 1 PFLAG3_TEMPORARY_DETACH
* |-------|-------|-------|-------|
*/
@@ -2667,6 +2668,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
+ /**
+ * Flag indicating that the view is temporarily detached from the parent view.
+ *
+ * @see #onStartTemporaryDetach()
+ * @see #onFinishTemporaryDetach()
+ */
+ static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
+
/* End of masks for mPrivateFlags3 */
/**
@@ -3890,6 +3899,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* cleanup.
*/
final RenderNode mRenderNode;
+ private Runnable mRenderNodeDetachedCallback;
/**
* Set to true when the view is sending hover accessibility events because it
@@ -9735,9 +9745,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * @hide
+ * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
+ * and {@link #onFinishTemporaryDetach()}.
*/
+ public final boolean isTemporarilyDetached() {
+ return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
+ }
+
+ /**
+ * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
+ * a container View.
+ */
+ @CallSuper
public void dispatchStartTemporaryDetach() {
+ mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
onStartTemporaryDetach();
}
@@ -9753,10 +9774,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * @hide
+ * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
+ * a container View.
*/
+ @CallSuper
public void dispatchFinishTemporaryDetach() {
onFinishTemporaryDetach();
+ mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
}
/**
@@ -15187,6 +15211,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
protected void onDetachedFromWindowInternal() {
mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
+ mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
removeUnsetPressCallback();
removeLongPressCallback();
@@ -16013,6 +16038,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public void onRenderNodeDetached(RenderNode renderNode) {
+ if (renderNode == mRenderNode && mRenderNodeDetachedCallback != null) {
+ mRenderNodeDetachedCallback.run();
+ }
+ }
+
+ /**
+ * Set callback for functor detach. Exposed to WebView through WebViewDelegate.
+ * Should not be used otherwise.
+ * @hide
+ */
+ public final Runnable setRenderNodeDetachedCallback(@Nullable Runnable callback) {
+ Runnable oldCallback = mRenderNodeDetachedCallback;
+ mRenderNodeDetachedCallback = callback;
+ return oldCallback;
}
/**
@@ -16915,7 +16954,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
} else if (cache != null) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
- if (layerType == LAYER_TYPE_NONE) {
+ if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
// no layer paint, use temporary paint to draw bitmap
Paint cachePaint = parent.mCachePaint;
if (cachePaint == null) {
@@ -16927,13 +16966,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
} else {
// use layer paint to draw the bitmap, merging the two alphas, but also restore
- int layerPaintAlpha = mLayerPaint != null ? mLayerPaint.getAlpha() : 255;
- if (mLayerPaint == null && alpha < 1) {
- mLayerPaint = new Paint();
+ int layerPaintAlpha = mLayerPaint.getAlpha();
+ if (alpha < 1) {
mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
}
canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
- if (mLayerPaint != null) {
+ if (alpha < 1) {
mLayerPaint.setAlpha(layerPaintAlpha);
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 420c4f272ff0..5b2877faef02 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3415,6 +3415,13 @@ public final class ViewRootImpl implements ViewParent,
updateConfiguration(config, false);
}
+ final boolean framesChanged = !mWinFrame.equals(args.arg1)
+ || !mPendingOverscanInsets.equals(args.arg5)
+ || !mPendingContentInsets.equals(args.arg2)
+ || !mPendingStableInsets.equals(args.arg6)
+ || !mPendingVisibleInsets.equals(args.arg3)
+ || !mPendingOutsets.equals(args.arg7);
+
mWinFrame.set((Rect) args.arg1);
mPendingOverscanInsets.set((Rect) args.arg5);
mPendingContentInsets.set((Rect) args.arg2);
@@ -3431,7 +3438,7 @@ public final class ViewRootImpl implements ViewParent,
mReportNextDraw = true;
}
- if (mView != null) {
+ if (mView != null && framesChanged) {
forceLayout(mView);
}
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index b72107447541..737e46071313 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -44,6 +44,8 @@ public class WindowInfo implements Parcelable {
public boolean focused;
public final Rect boundsInScreen = new Rect();
public List<IBinder> childTokens;
+ public CharSequence title;
+ public int accessibilityIdOfAnchor = View.NO_ID;
private WindowInfo() {
/* do nothing - hide constructor */
@@ -65,6 +67,8 @@ public class WindowInfo implements Parcelable {
window.parentToken = other.parentToken;
window.focused = other.focused;
window.boundsInScreen.set(other.boundsInScreen);
+ window.title = other.title;
+ window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
if (other.childTokens != null && !other.childTokens.isEmpty()) {
if (window.childTokens == null) {
@@ -95,6 +99,8 @@ public class WindowInfo implements Parcelable {
parcel.writeStrongBinder(parentToken);
parcel.writeInt(focused ? 1 : 0);
boundsInScreen.writeToParcel(parcel, flags);
+ parcel.writeCharSequence(title);
+ parcel.writeInt(accessibilityIdOfAnchor);
if (childTokens != null && !childTokens.isEmpty()) {
parcel.writeInt(1);
@@ -108,13 +114,15 @@ public class WindowInfo implements Parcelable {
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("WindowInfo[");
- builder.append("type=").append(type);
+ builder.append("title=").append(title);
+ builder.append(", type=").append(type);
builder.append(", layer=").append(layer);
builder.append(", token=").append(token);
builder.append(", bounds=").append(boundsInScreen);
builder.append(", parent=").append(parentToken);
builder.append(", focused=").append(focused);
builder.append(", children=").append(childTokens);
+ builder.append(", accessibility anchor=").append(accessibilityIdOfAnchor);
builder.append(']');
return builder.toString();
}
@@ -126,6 +134,8 @@ public class WindowInfo implements Parcelable {
parentToken = parcel.readStrongBinder();
focused = (parcel.readInt() == 1);
boundsInScreen.readFromParcel(parcel);
+ title = parcel.readCharSequence();
+ accessibilityIdOfAnchor = parcel.readInt();
final boolean hasChildren = (parcel.readInt() == 1);
if (hasChildren) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 03dcf99258ab..c372c30915f2 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1693,6 +1693,14 @@ public interface WindowManager extends ViewManager {
*/
public long userActivityTimeout = -1;
+ /**
+ * For windows with an anchor (e.g. PopupWindow), keeps track of the View that anchors the
+ * window.
+ *
+ * @hide
+ */
+ public int accessibilityIdOfAnchor = -1;
+
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
@@ -1799,6 +1807,7 @@ public interface WindowManager extends ViewManager {
out.writeInt(surfaceInsets.bottom);
out.writeInt(hasManualSurfaceInsets ? 1 : 0);
out.writeInt(needsMenuKey);
+ out.writeInt(accessibilityIdOfAnchor);
}
public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1849,6 +1858,7 @@ public interface WindowManager extends ViewManager {
surfaceInsets.bottom = in.readInt();
hasManualSurfaceInsets = in.readInt() != 0;
needsMenuKey = in.readInt();
+ accessibilityIdOfAnchor = in.readInt();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -1888,6 +1898,8 @@ public interface WindowManager extends ViewManager {
/** {@hide} */
public static final int PREFERRED_DISPLAY_MODE_ID = 1 << 23;
/** {@hide} */
+ public static final int ACCESSIBILITY_ANCHOR_CHANGED = 1 << 24;
+ /** {@hide} */
public static final int EVERYTHING_CHANGED = 0xffffffff;
// internal buffer to backup/restore parameters under compatibility mode.
@@ -2048,6 +2060,11 @@ public interface WindowManager extends ViewManager {
changes |= NEEDS_MENU_KEY_CHANGED;
}
+ if (accessibilityIdOfAnchor != o.accessibilityIdOfAnchor) {
+ accessibilityIdOfAnchor = o.accessibilityIdOfAnchor;
+ changes |= ACCESSIBILITY_ANCHOR_CHANGED;
+ }
+
return changes;
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 23b0df2db110..96f179b8db63 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1397,4 +1397,9 @@ public interface WindowManagerPolicy {
* is allowed, so for example, if DOCKED_RIGHT is not allowed, DOCKED_LEFT is allowed.
*/
public boolean isDockSideAllowed(int dockSide);
+
+ /**
+ * Called when the configuration has changed, and it's safe to load new values from resources.
+ */
+ public void onConfigurationChanged();
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 2cde03d63529..f8a13a373aec 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -240,10 +240,12 @@ import java.util.List;
* <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text
* was traversed.</li>
* <li>{@link #getText()} - The text of the source's sub-tree.</li>
- * <li>{@link #getFromIndex()} - The start of the next/previous text at the specified granularity
- * - inclusive.</li>
- * <li>{@link #getToIndex()} - The end of the next/previous text at the specified granularity
- * - exclusive.</li>
+ * <li>{@link #getFromIndex()} - The start the text that was skipped over in this movement.
+ * This is the starting point when moving forward through the text, but not when moving
+ * back.</li>
+ * <li>{@link #getToIndex()} - The end of the text that was skipped over in this movement.
+ * This is the ending point when moving forward through the text, but not when moving
+ * back.</li>
* <li>{@link #isPassword()} - Whether the source is password.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #getContentDescription()} - The content description of the source.</li>
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 14821118f728..02d2a8bd386f 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -328,36 +328,6 @@ public class AccessibilityNodeInfo implements Parcelable {
// Action arguments
/**
- * Argument for specifying index of {@link android.text.style.ClickableSpan} the click action is
- * related to.
- * <p>
- * <strong>Type:</strong> int<br>
- * <strong>Actions:</strong>
- * {@link AccessibilityAction#ACTION_CLICK}
- * </p>
- *
- * @see AccessibilityAction#ACTION_CLICK
- */
- public static final String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT =
- "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
-
- /**
- * Argument for specifying index of character in the text which contains
- * {@link android.text.style.ClickableSpan} the click action is
- * related to. If there is more than one {@link android.text.style.ClickableSpan} assigned for
- * the range the character is in only the first span would be clicked.
- * <p>
- * <strong>Type:</strong> int<br>
- * <strong>Actions:</strong>
- * {@link AccessibilityAction#ACTION_CLICK}
- * </p>
- *
- * @see AccessibilityAction#ACTION_CLICK
- */
- public static final String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT =
- "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
-
- /**
* Argument for which movement granularity to be used when traversing the node text.
* <p>
* <strong>Type:</strong> int<br>
@@ -3391,33 +3361,6 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Action that clicks on the node info.
- *
- * <p>
- * If a specific {@link android.text.style.ClickableSpan} within node's text content is
- * supposed to be clicked, then one of {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT} or
- * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} arguments should be specified.
- * If both arguments are set {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} would
- * be ignored.<br>
- *
- * {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT} specifies index of corresponding
- * {@link android.text.style.ClickableSpan} in {@link android.text.SpannableString}.<br>
- *
- * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} specifies index of character
- * that could contain one or more spans.
- * </p>
- *
- * <p>
- * <strong>Optional arguments:</strong>
- * {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT},
- * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT}<br>
- * <strong>Example:</strong> Perform click on 3rd {@link android.text.style.ClickableSpan}
- * inside {@link android.text.SpannableString} in node's text.
- * <code><pre><p>
- * Bundle arguments = new Bundle();
- * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT, 3);
- * info.performAction(AccessibilityAction.ACTION_CLICK.getId(), arguments);
- * </code></pre></p>
- * </p>
*/
public static final AccessibilityAction ACTION_CLICK =
new AccessibilityAction(
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index ad78b686b8de..d0d4507e7b62 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -89,6 +89,8 @@ public final class AccessibilityWindowInfo implements Parcelable {
private int mParentId = UNDEFINED;
private final Rect mBoundsInScreen = new Rect();
private LongArray mChildIds;
+ private CharSequence mTitle;
+ private int mAnchorId = UNDEFINED;
private int mConnectionId = UNDEFINED;
@@ -97,6 +99,26 @@ public final class AccessibilityWindowInfo implements Parcelable {
}
/**
+ * Gets the title of the window.
+ *
+ * @return The title.
+ */
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * Sets the title of the window.
+ *
+ * @param title The title.
+ *
+ * @hide
+ */
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ }
+
+ /**
* Gets the type of the window.
*
* @return The type.
@@ -159,9 +181,35 @@ public final class AccessibilityWindowInfo implements Parcelable {
}
/**
- * Gets the parent window if such.
+ * Sets the anchor node's ID.
+ *
+ * @param anchorId The anchor's accessibility id in its window.
+ *
+ * @hide
+ */
+ public void setAnchorId(int anchorId) {
+ mAnchorId = anchorId;
+ }
+
+ /**
+ * Gets the node that anchors this window to another.
+ *
+ * @return The anchor node, or {@code null} if none exists.
+ */
+ public AccessibilityNodeInfo getAnchor() {
+ if ((mConnectionId == UNDEFINED) || (mAnchorId == UNDEFINED) || (mParentId == UNDEFINED)) {
+ return null;
+ }
+
+ AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
+ mParentId, mAnchorId, true, 0);
+ }
+
+ /**
+ * Gets the parent window.
*
- * @return The parent window.
+ * @return The parent window, or {@code null} if none exists.
*/
public AccessibilityWindowInfo getParent() {
if (mConnectionId == UNDEFINED || mParentId == UNDEFINED) {
@@ -370,6 +418,8 @@ public final class AccessibilityWindowInfo implements Parcelable {
infoClone.mId = info.mId;
infoClone.mParentId = info.mParentId;
infoClone.mBoundsInScreen.set(info.mBoundsInScreen);
+ infoClone.mTitle = info.mTitle;
+ infoClone.mAnchorId = info.mAnchorId;
if (info.mChildIds != null && info.mChildIds.size() > 0) {
if (infoClone.mChildIds == null) {
@@ -410,6 +460,8 @@ public final class AccessibilityWindowInfo implements Parcelable {
parcel.writeInt(mId);
parcel.writeInt(mParentId);
mBoundsInScreen.writeToParcel(parcel, flags);
+ parcel.writeCharSequence(mTitle);
+ parcel.writeInt(mAnchorId);
final LongArray childIds = mChildIds;
if (childIds == null) {
@@ -432,6 +484,8 @@ public final class AccessibilityWindowInfo implements Parcelable {
mId = parcel.readInt();
mParentId = parcel.readInt();
mBoundsInScreen.readFromParcel(parcel);
+ mTitle = parcel.readCharSequence();
+ mAnchorId = parcel.readInt();
final int childCount = parcel.readInt();
if (childCount > 0) {
@@ -471,6 +525,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("AccessibilityWindowInfo[");
+ builder.append("title=").append(mTitle);
builder.append("id=").append(mId);
builder.append(", type=").append(typeToString(mType));
builder.append(", layer=").append(mLayer);
@@ -494,6 +549,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
builder.append(']');
} else {
builder.append(", hasParent=").append(mParentId != UNDEFINED);
+ builder.append(", isAnchored=").append(mAnchorId != UNDEFINED);
builder.append(", hasChildren=").append(mChildIds != null
&& mChildIds.size() > 0);
}
@@ -515,6 +571,8 @@ public final class AccessibilityWindowInfo implements Parcelable {
mChildIds.clear();
}
mConnectionId = UNDEFINED;
+ mAnchorId = UNDEFINED;
+ mTitle = null;
}
/**
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 1536c29bee5b..d89c172be8a7 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -93,8 +93,12 @@ public abstract class Animation implements Cloneable {
*/
public static final int ZORDER_BOTTOM = -1;
- private static final boolean USE_CLOSEGUARD
- = SystemProperties.getBoolean("log.closeguard.Animation", false);
+ // Use a preload holder to isolate static initialization into inner class, which allows
+ // Animation and its subclasses to be compile-time initialized.
+ private static class NoImagePreloadHolder {
+ public static final boolean USE_CLOSEGUARD
+ = SystemProperties.getBoolean("log.closeguard.Animation", false);
+ }
/**
* Set by {@link #getTransformation(long, Transformation)} when the animation ends.
@@ -859,7 +863,7 @@ public abstract class Animation implements Cloneable {
if (!mStarted) {
fireAnimationStart();
mStarted = true;
- if (USE_CLOSEGUARD) {
+ if (NoImagePreloadHolder.USE_CLOSEGUARD) {
guard.open("cancel or detach or getTransformation");
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 687990124a55..1ce804342c43 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1307,6 +1307,12 @@ public final class InputMethodManager {
void focusInLocked(View view) {
if (DEBUG) Log.v(TAG, "focusIn: " + dumpViewInfo(view));
+ if (view != null && view.isTemporarilyDetached()) {
+ // This is a request from a view that is temporarily detached from a window.
+ if (DEBUG) Log.v(TAG, "Temporarily detached view, ignoring");
+ return;
+ }
+
if (mCurRootView != view.getRootView()) {
// This is a request from a window that isn't in the window with
// IME focus, so ignore it.
@@ -1332,6 +1338,7 @@ public final class InputMethodManager {
// whenever we go into touch mode, so it ends up hiding
// at times when we don't really want it to. For now it
// seems better to just turn it all off.
+ // TODO: Check view.isTemporarilyDetached() when re-enable the following code.
if (false && view.hasWindowFocus()) {
mNextServedView = null;
scheduleCheckFocusLocked(view);
@@ -1348,7 +1355,7 @@ public final class InputMethodManager {
synchronized (mH) {
if (DEBUG) Log.v(TAG, "onViewDetachedFromWindow: view=" + dumpViewInfo(view)
+ " mServedView=" + dumpViewInfo(mServedView));
- if (mServedView == view && view.hasWindowFocus()) {
+ if (mServedView == view) {
mNextServedView = null;
scheduleCheckFocusLocked(view);
}
@@ -2315,6 +2322,7 @@ public final class InputMethodManager {
sb.append(",focus=" + view.hasFocus());
sb.append(",windowFocus=" + view.hasWindowFocus());
sb.append(",window=" + view.getWindowToken());
+ sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
return sb.toString();
}
}
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 8104f7d6f50c..b6516c85d094 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -16,6 +16,8 @@
package android.webkit;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.Application;
@@ -109,6 +111,24 @@ public final class WebViewDelegate {
}
/**
+ * Set the Runnable callback the DrawGlFunction functor is detached and free to be destroyed.
+ * This will replace the previous callback, if any.
+ *
+ * @param view The view to set the callback. Should be the view where onDraw inserted
+ * DrawGLFunctor.
+ * @param callback The new callback to set on the view.
+ * @throws IllegalArgumentException if view is null.
+ * @return The previous callback on this view.
+ */
+ public Runnable setDrawGlFunctionDetachedCallback(
+ @NonNull View view, @Nullable Runnable callback) {
+ if (view == null) {
+ throw new IllegalArgumentException("View cannot be null");
+ }
+ return view.setRenderNodeDetachedCallback(callback);
+ }
+
+ /**
* Detaches the draw GL functor.
*
* @param nativeDrawGLFunctor the pointer to the native functor that implements
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index cc496dc72d7c..0ac57319d5de 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -21,7 +21,6 @@ import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.Application;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -561,18 +560,6 @@ public final class WebViewFactory {
return result;
}
- /**
- * Returns whether the entire package from an ACTION_PACKAGE_CHANGED intent was changed (rather
- * than just one of its components).
- * @hide
- */
- public static boolean entirePackageChanged(Intent intent) {
- String[] componentList =
- intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
- return Arrays.asList(componentList).contains(
- intent.getDataString().substring("package:".length()));
- }
-
private static String WEBVIEW_UPDATE_SERVICE_NAME = "webviewupdate";
/** @hide */
diff --git a/core/java/android/widget/AccessibilityIterators.java b/core/java/android/widget/AccessibilityIterators.java
index a3d58a4e2060..442ffa136ca3 100644
--- a/core/java/android/widget/AccessibilityIterators.java
+++ b/core/java/android/widget/AccessibilityIterators.java
@@ -134,8 +134,8 @@ final class AccessibilityIterators {
@Override
public int[] following(int offset) {
- final int textLegth = mText.length();
- if (textLegth <= 0) {
+ final int textLength = mText.length();
+ if (textLength <= 0) {
return null;
}
if (offset >= mText.length()) {
@@ -163,8 +163,8 @@ final class AccessibilityIterators {
@Override
public int[] preceding(int offset) {
- final int textLegth = mText.length();
- if (textLegth <= 0) {
+ final int textLength = mText.length();
+ if (textLength <= 0) {
return null;
}
if (offset <= 0) {
@@ -181,8 +181,13 @@ final class AccessibilityIterators {
final int pageHeight = mTempRect.height() - mView.getTotalPaddingTop()
- mView.getTotalPaddingBottom();
final int previousPageEndY = currentLineTop - pageHeight;
- final int currentPageStartLine = (previousPageEndY > 0) ?
- mLayout.getLineForVertical(previousPageEndY) + 1 : 0;
+ int currentPageStartLine = (previousPageEndY > 0) ?
+ mLayout.getLineForVertical(previousPageEndY) : 0;
+ // If we're at the end of text, we're at the end of the current line rather than the
+ // start of the next line, so we should move up one fewer lines than we would otherwise.
+ if (end == mText.length() && (currentPageStartLine < currentLine)) {
+ currentPageStartLine += 1;
+ }
final int start = getLineEdgeIndex(currentPageStartLine, DIRECTION_START);
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 7d57cb83f6df..6a4e36a9a578 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -1116,7 +1116,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
- if (mTemporaryDetach) {
+ if (isTemporarilyDetached()) {
// If we are temporarily in the detach state, then do nothing.
return;
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index cde7604b7e7c..66896ab70e45 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -430,9 +430,11 @@ public class CalendarView extends FrameLayout {
* Sets whether to show the week number.
*
* @param showWeekNumber True to show the week number.
+ * @deprecated No longer used by Material-style CalendarView.
*
* @attr ref android.R.styleable#CalendarView_showWeekNumber
*/
+ @Deprecated
public void setShowWeekNumber(boolean showWeekNumber) {
mDelegate.setShowWeekNumber(showWeekNumber);
}
@@ -441,9 +443,11 @@ public class CalendarView extends FrameLayout {
* Gets whether to show the week number.
*
* @return True if showing the week number.
+ * @deprecated No longer used by Material-style CalendarView.
*
* @attr ref android.R.styleable#CalendarView_showWeekNumber
*/
+ @Deprecated
public boolean getShowWeekNumber() {
return mDelegate.getShowWeekNumber();
}
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 442fb334c4f6..f540479ad641 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -404,7 +404,7 @@ class CalendarViewLegacyDelegate extends CalendarView.AbstractCalendarViewDelega
@Override
public int getUnfocusedMonthDateColor() {
- return mFocusedMonthDateColor;
+ return mUnfocusedMonthDateColor;
}
@Override
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index e3357a7738f2..0c5edc5f2f81 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -339,7 +339,9 @@ public class DatePicker extends FrameLayout {
*
* @return {@code true} if the calendar view is shown
* @see #getCalendarView()
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public boolean getCalendarViewShown() {
return mDelegate.getCalendarViewShown();
}
@@ -347,13 +349,18 @@ public class DatePicker extends FrameLayout {
/**
* Returns the {@link CalendarView} used by this picker.
* <p>
- * <strong>Note:</strong> This method returns {@code null} when the
+ * <strong>Note:</strong> This method throws an
+ * {@link UnsupportedOperationException} when the
* {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
* to {@code calendar}.
*
* @return the calendar view
* @see #getCalendarViewShown()
+ * @deprecated Not supported by Material-style {@code calendar} mode
+ * @throws UnsupportedOperationException if called when the picker is
+ * displayed in {@code calendar} mode
*/
+ @Deprecated
public CalendarView getCalendarView() {
return mDelegate.getCalendarView();
}
@@ -367,7 +374,9 @@ public class DatePicker extends FrameLayout {
*
* @param shown {@code true} to show the calendar view, {@code false} to
* hide it
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public void setCalendarViewShown(boolean shown) {
mDelegate.setCalendarViewShown(shown);
}
@@ -380,7 +389,9 @@ public class DatePicker extends FrameLayout {
* to {@code calendar}.
*
* @return {@code true} if the spinners are shown
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public boolean getSpinnersShown() {
return mDelegate.getSpinnersShown();
}
@@ -394,7 +405,9 @@ public class DatePicker extends FrameLayout {
*
* @param shown {@code true} to show the spinners, {@code false} to hide
* them
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public void setSpinnersShown(boolean shown) {
mDelegate.setSpinnersShown(shown);
}
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 8ce2f9cb470c..97936e7c7c5b 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -148,18 +148,22 @@ class DayPickerPagerAdapter extends PagerAdapter {
void setCalendarTextColor(ColorStateList calendarTextColor) {
mCalendarTextColor = calendarTextColor;
+ notifyDataSetChanged();
}
void setDaySelectorColor(ColorStateList selectorColor) {
mDaySelectorColor = selectorColor;
+ notifyDataSetChanged();
}
void setMonthTextAppearance(int resId) {
mMonthTextAppearance = resId;
+ notifyDataSetChanged();
}
void setDayOfWeekTextAppearance(int resId) {
mDayOfWeekTextAppearance = resId;
+ notifyDataSetChanged();
}
int getDayOfWeekTextAppearance() {
@@ -168,6 +172,7 @@ class DayPickerPagerAdapter extends PagerAdapter {
void setDayTextAppearance(int resId) {
mDayTextAppearance = resId;
+ notifyDataSetChanged();
}
int getDayTextAppearance() {
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 434e3eb8237e..ad355504a0ee 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -155,6 +155,9 @@ public class EditText extends TextView {
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
switch (action) {
case AccessibilityNodeInfo.ACTION_SET_TEXT: {
+ if (!isEnabled()) {
+ return false;
+ }
CharSequence text = (arguments != null) ? arguments.getCharSequence(
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;
setText(text);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 59d857c35afe..440ef2162fc5 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -218,7 +218,6 @@ public class Editor {
boolean mShowSoftInputOnFocus = true;
private boolean mPreserveSelection;
private boolean mRestartActionModeOnNextRefresh;
- boolean mTemporaryDetach;
boolean mIsBeingLongClicked;
@@ -367,7 +366,6 @@ public class Editor {
showError();
mShowErrorAfterAttach = false;
}
- mTemporaryDetach = false;
final ViewTreeObserver observer = mTextView.getViewTreeObserver();
// No need to create the controller.
@@ -429,7 +427,6 @@ public class Editor {
hideCursorAndSpanControllers();
stopTextActionModeWithPreservingSelection();
- mTemporaryDetach = false;
}
private void discardTextDisplayLists() {
@@ -1212,7 +1209,7 @@ public class Editor {
stopTextActionModeWithPreservingSelection();
} else {
hideCursorAndSpanControllers();
- if (mTemporaryDetach) {
+ if (mTextView.isTemporarilyDetached()) {
stopTextActionModeWithPreservingSelection();
} else {
stopTextActionMode();
@@ -1781,6 +1778,18 @@ public class Editor {
if (translate) canvas.translate(0, -cursorOffsetVertical);
}
+ void invalidateHandlesAndActionMode() {
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.invalidateHandles();
+ }
+ if (mInsertionPointCursorController != null) {
+ mInsertionPointCursorController.invalidateHandle();
+ }
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidate();
+ }
+ }
+
/**
* Invalidates all the sub-display lists that overlap the specified character range
*/
@@ -1866,9 +1875,9 @@ public class Editor {
if (hasSelection) {
hideInsertionPointCursorController();
if (mTextActionMode == null) {
- if (mRestartActionModeOnNextRefresh || mTextView.isInExtractedMode()) {
+ if (mRestartActionModeOnNextRefresh) {
// To avoid distraction, newly start action mode only when selection action
- // mode is being restarted or in full screen extracted mode.
+ // mode is being restarted.
startSelectionActionMode();
}
} else if (selectionController == null || !selectionController.isActive()) {
@@ -3465,7 +3474,6 @@ public class Editor {
popupBackground.getPadding(mTempRect);
width += mTempRect.left + mTempRect.right;
}
- mSuggestionListView.getLayoutParams().width = width;
mPopupWindow.setWidth(width);
}
@@ -3640,6 +3648,9 @@ public class Editor {
}
if (menu.hasVisibleItems() || mode.getCustomView() != null) {
+ if (mHasSelection && !mTextView.hasTransientState()) {
+ mTextView.setHasTransientState(true);
+ }
return true;
} else {
return false;
@@ -4104,6 +4115,14 @@ public class Editor {
setMeasuredDimension(getPreferredWidth(), getPreferredHeight());
}
+ @Override
+ public void invalidate() {
+ super.invalidate();
+ if (isShowing()) {
+ positionAtCursorOffset(getCurrentCursorOffset(), true);
+ }
+ };
+
private int getPreferredWidth() {
return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
}
@@ -4170,7 +4189,12 @@ public class Editor {
return mTextView.getOffsetAtCoordinate(line, x);
}
- protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+ /**
+ * @param offset Cursor offset. Must be in [-1, length].
+ * @param forceUpdatePosition whether to force update the position. This should be true
+ * when If the parent has been scrolled, for example.
+ */
+ protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
// A HandleView relies on the layout, which may be nulled by external methods
Layout layout = mTextView.getLayout();
if (layout == null) {
@@ -4181,7 +4205,7 @@ public class Editor {
layout = mTextView.getLayout();
boolean offsetChanged = offset != mPreviousOffset;
- if (offsetChanged || parentScrolled) {
+ if (offsetChanged || forceUpdatePosition) {
if (offsetChanged) {
updateSelection(offset);
addPositionToTouchUpFilter(offset);
@@ -4782,13 +4806,9 @@ public class Editor {
mPrevX = x;
}
- /**
- * @param offset Cursor offset. Must be in [-1, length].
- * @param parentScrolled If the parent has been scrolled or not.
- */
@Override
- protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
- super.positionAtCursorOffset(offset, parentScrolled);
+ protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
+ super.positionAtCursorOffset(offset, forceUpdatePosition);
mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset);
}
@@ -4875,11 +4895,12 @@ public class Editor {
@Override
protected int getOffsetAtCoordinate(@NonNull Layout layout, int line, float x) {
- final int primaryOffset = layout.getOffsetForHorizontal(line, x, true);
+ final float localX = mTextView.convertToLocalHorizontalCoordinate(x);
+ final int primaryOffset = layout.getOffsetForHorizontal(line, localX, true);
if (!layout.isLevelBoundary(primaryOffset)) {
return primaryOffset;
}
- final int secondaryOffset = layout.getOffsetForHorizontal(line, x, false);
+ final int secondaryOffset = layout.getOffsetForHorizontal(line, localX, false);
final int currentOffset = getCurrentCursorOffset();
final int primaryDiff = Math.abs(primaryOffset - currentOffset);
final int secondaryDiff = Math.abs(secondaryOffset - currentOffset);
@@ -5013,6 +5034,12 @@ public class Editor {
public boolean isActive() {
return mHandle != null && mHandle.isShowing();
}
+
+ public void invalidateHandle() {
+ if (mHandle != null) {
+ mHandle.invalidate();
+ }
+ }
}
class SelectionModifierCursorController implements CursorController {
@@ -5417,6 +5444,15 @@ public class Editor {
public boolean isActive() {
return mStartHandle != null && mStartHandle.isShowing();
}
+
+ public void invalidateHandles() {
+ if (mStartHandle != null) {
+ mStartHandle.invalidate();
+ }
+ if (mEndHandle != null) {
+ mEndHandle.invalidate();
+ }
+ }
}
private class CorrectionHighlighter {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 7658cc894913..bfc87f297d42 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1673,7 +1673,7 @@ public class ListView extends AbsListView {
focusLayoutRestoreView = findFocus();
if (focusLayoutRestoreView != null) {
// Tell it we are going to mess with it.
- focusLayoutRestoreView.onStartTemporaryDetach();
+ focusLayoutRestoreView.dispatchStartTemporaryDetach();
}
}
requestFocus();
@@ -1850,7 +1850,7 @@ public class ListView extends AbsListView {
// our view hierarchy.
if (focusLayoutRestoreView != null
&& focusLayoutRestoreView.getWindowToken() != null) {
- focusLayoutRestoreView.onFinishTemporaryDetach();
+ focusLayoutRestoreView.dispatchFinishTemporaryDetach();
}
mLayoutMode = LAYOUT_NORMAL;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 92631da2da90..0d8d8ed17b65 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1214,6 +1214,7 @@ public class PopupWindow {
final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
p.width, p.height, gravity);
updateAboveAnchor(aboveAnchor);
+ p.accessibilityIdOfAnchor = (anchor != null) ? anchor.getAccessibilityViewId() : -1;
invokePopup(p);
}
@@ -1494,7 +1495,7 @@ public class PopupWindow {
*
* @param anchor the view on which the popup window must be anchored
* @param outParams the layout parameters used to display the drop down
- * @param xOffset absolute horizontal offset from the top of the anchor
+ * @param xOffset absolute horizontal offset from the left of the anchor
* @param yOffset absolute vertical offset from the top of the anchor
* @param gravity horizontal gravity specifying popup alignment
* @return true if the popup is translated upwards to fit on screen
@@ -1523,6 +1524,8 @@ public class PopupWindow {
// Let the window manager know to align the top to y.
outParams.gravity = Gravity.LEFT | Gravity.TOP;
+ outParams.width = width;
+ outParams.height = height;
final int[] screenLocation = mTmpScreenLocation;
anchor.getLocationOnScreen(screenLocation);
@@ -1530,100 +1533,154 @@ public class PopupWindow {
final Rect displayFrame = new Rect();
anchor.getWindowVisibleDisplayFrame(displayFrame);
- boolean onTop = false;
-
- final View root = anchor.getRootView();
- final int screenY = screenLocation[1] + anchorHeight + yOffset;
- final boolean tooFarDown = screenY + height > displayFrame.bottom;
- final boolean tooFarRight = outParams.x + width > root.getWidth();
- if (tooFarDown || tooFarRight) {
- // If the popup extends beyond the visible area, try to scroll the
- // parent so that it is fully visible.
- if (mAllowScrollingAnchorParent) {
- final int scrollX = anchor.getScrollX();
- final int scrollY = anchor.getScrollY();
- final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
- scrollY + height + anchorHeight + yOffset);
- anchor.requestRectangleOnScreen(r, true);
+ // First, attempt to fit the popup vertically without resizing.
+ final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
+ anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
+ displayFrame.bottom, false);
+
+ // Next, attempt to fit the popup horizontally without resizing.
+ final boolean fitsHorizontal = tryFitHorizontal(outParams, xOffset, width,
+ anchorWidth, drawingLocation[0], screenLocation[0], displayFrame.left,
+ displayFrame.right, false);
+
+ // If the popup still doesn't fit, attempt to scroll the parent.
+ if (!fitsVertical || !fitsHorizontal) {
+ final int scrollX = anchor.getScrollX();
+ final int scrollY = anchor.getScrollY();
+ final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
+ scrollY + height + anchorHeight + yOffset);
+ if (mAllowScrollingAnchorParent && anchor.requestRectangleOnScreen(r, true)) {
+ // Reset for the new anchor position.
+ anchor.getLocationInWindow(drawingLocation);
+ outParams.x = drawingLocation[0] + xOffset;
+ outParams.y = drawingLocation[1] + anchorHeight + yOffset;
+
+ // Preserve the gravity adjustment.
+ if (hgrav == Gravity.RIGHT) {
+ outParams.x -= width - anchorWidth;
+ }
}
- // Update for the new anchor position.
- anchor.getLocationInWindow(drawingLocation);
- outParams.x = drawingLocation[0] + xOffset;
- outParams.y = drawingLocation[1] + anchorHeight + yOffset;
+ // Try to fit the popup again and allowing resizing.
+ tryFitVertical(outParams, yOffset, height, anchorHeight, drawingLocation[1],
+ screenLocation[1], displayFrame.top, displayFrame.bottom, mClipToScreen);
+ tryFitHorizontal(outParams, xOffset, width, anchorWidth, drawingLocation[0],
+ screenLocation[0], displayFrame.left, displayFrame.right, mClipToScreen);
+ }
- // Preserve the gravity adjustment.
- if (hgrav == Gravity.RIGHT) {
- outParams.x -= width - anchorWidth;
- }
+ // Return whether the popup's top edge is above the anchor's top edge.
+ return outParams.y < drawingLocation[1];
+ }
- final int newScreenY = screenLocation[1] + anchorHeight + yOffset;
- final boolean stillTooFarDown = newScreenY + height > displayFrame.bottom;
- if (stillTooFarDown) {
- // If the popup is still too far down, re-evaluate the space
- // available and decide whether the pop-up will go above or
- // below the anchor.
- anchor.getLocationOnScreen(screenLocation);
-
- final int below = displayFrame.bottom - screenLocation[1] - anchorHeight - yOffset;
- final int above = screenLocation[1] - displayFrame.top + yOffset;
- onTop = above > below;
-
- if (onTop) {
- // Move everything up.
- if (mOverlapAnchor) {
- yOffset += anchorHeight;
- }
- outParams.y = drawingLocation[1] - height + yOffset;
- }
+ private boolean tryFitVertical(@NonNull LayoutParams outParams, int yOffset, int height,
+ int anchorHeight, int drawingLocationY, int screenLocationY, int displayFrameTop,
+ int displayFrameBottom, boolean allowResize) {
+ final int anchorTopInScreen = screenLocationY + anchorHeight + yOffset;
+ final int spaceBelow = displayFrameBottom - anchorTopInScreen;
+ if (height <= spaceBelow) {
+ return true;
+ }
+
+ final int spaceAbove = displayFrameTop + anchorTopInScreen - anchorHeight;
+ if (height <= spaceAbove) {
+ // Move everything up.
+ if (mOverlapAnchor) {
+ yOffset += anchorHeight;
}
+ outParams.y = drawingLocationY - height + yOffset;
+
+ return true;
}
- if (mClipToScreen) {
- // Use screen coordinates for comparison against display frame.
- final int winOffsetX = screenLocation[0] - drawingLocation[0];
- final int winOffsetY = screenLocation[1] - drawingLocation[1];
- outParams.x += winOffsetX;
- outParams.y += winOffsetY;
+ if (positionInDisplayVertical(outParams, height, drawingLocationY, screenLocationY,
+ displayFrameTop, displayFrameBottom, allowResize)) {
+ return true;
+ }
- final int right = outParams.x + width;
- if (right > displayFrame.right) {
- // The popup is too far right, move it back in.
- outParams.x -= right - displayFrame.right;
- }
+ return false;
+ }
- if (outParams.x < displayFrame.left) {
- // The popup is too far left, move it back in and clip if it's
- // still too large.
- outParams.x = displayFrame.left;
+ private boolean positionInDisplayVertical(@NonNull LayoutParams outParams, int height,
+ int drawingLocationY, int screenLocationY, int displayFrameTop, int displayFrameBottom,
+ boolean canResize) {
+ boolean fitsInDisplay = true;
- final int displayFrameWidth = displayFrame.width();
- width = Math.min(width, displayFrameWidth);
- }
+ final int winOffsetY = screenLocationY - drawingLocationY;
+ outParams.y += winOffsetY;
+ outParams.height = height;
- final int bottom = outParams.y + height;
- if (bottom > displayFrame.bottom) {
- // The popup is too far down, move it back in.
- outParams.y -= bottom - displayFrame.bottom;
- }
+ final int bottom = outParams.y + height;
+ if (bottom > displayFrameBottom) {
+ // The popup is too far down, move it back in.
+ outParams.y -= bottom - displayFrameBottom;
+ }
- if (outParams.y < displayFrame.top) {
- // The popup is too far up, move it back in and clip if
- // it's still too large.
- outParams.y = displayFrame.top;
+ if (outParams.y < displayFrameTop) {
+ // The popup is too far up, move it back in and clip if
+ // it's still too large.
+ outParams.y = displayFrameTop;
- final int displayFrameHeight = displayFrame.height();
- height = Math.min(height, displayFrameHeight);
+ final int displayFrameHeight = displayFrameBottom - displayFrameTop;
+ if (canResize && height > displayFrameHeight) {
+ outParams.height = displayFrameHeight;
+ } else {
+ fitsInDisplay = false;
}
+ }
+
+ outParams.y -= winOffsetY;
- outParams.x -= winOffsetX;
- outParams.y -= winOffsetY;
+ return fitsInDisplay;
+ }
+
+ private boolean tryFitHorizontal(@NonNull LayoutParams outParams, int xOffset, int width,
+ int anchorWidth, int drawingLocationX, int screenLocationX, int displayFrameLeft,
+ int displayFrameRight, boolean allowResize) {
+ final int anchorLeftInScreen = screenLocationX + xOffset;
+ final int spaceRight = displayFrameRight - anchorLeftInScreen;
+ if (width <= spaceRight) {
+ return true;
}
- outParams.width = width;
- outParams.height = height;
+ if (positionInDisplayHorizontal(outParams, width, drawingLocationX, screenLocationX,
+ displayFrameLeft, displayFrameRight, allowResize)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean positionInDisplayHorizontal(@NonNull LayoutParams outParams, int width,
+ int drawingLocationX, int screenLocationX, int displayFrameLeft, int displayFrameRight,
+ boolean canResize) {
+ boolean fitsInDisplay = true;
+
+ // Use screen coordinates for comparison against display frame.
+ final int winOffsetX = screenLocationX - drawingLocationX;
+ outParams.x += winOffsetX;
+
+ final int right = outParams.x + width;
+ if (right > displayFrameRight) {
+ // The popup is too far right, move it back in.
+ outParams.x -= right - displayFrameRight;
+ }
+
+ if (outParams.x < displayFrameLeft) {
+ // The popup is too far left, move it back in and clip if it's
+ // still too large.
+ outParams.x = displayFrameLeft;
+
+ final int displayFrameWidth = displayFrameRight - displayFrameLeft;
+ if (canResize && width > displayFrameWidth) {
+ outParams.width = displayFrameWidth;
+ } else {
+ fitsInDisplay = false;
+ }
+ }
+
+ outParams.x -= winOffsetX;
- return onTop;
+ return fitsInDisplay;
}
/**
@@ -1984,6 +2041,13 @@ public class PopupWindow {
update = true;
}
+ int newAccessibilityIdOfAnchor =
+ (mAnchor != null) ? mAnchor.get().getAccessibilityViewId() : -1;
+ if (newAccessibilityIdOfAnchor != p.accessibilityIdOfAnchor) {
+ p.accessibilityIdOfAnchor = newAccessibilityIdOfAnchor;
+ update = true;
+ }
+
if (update) {
setLayoutDirectionFromAnchor();
mWindowManager.updateViewLayout(mDecorView, p);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7602416fa751..48fd58b219db 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -330,10 +330,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private int mCurTextColor;
private int mCurHintTextColor;
private boolean mFreezesText;
- private boolean mDispatchTemporaryDetach;
-
- /** Whether this view is temporarily detached from the parent view. */
- boolean mTemporaryDetach;
private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
@@ -3354,7 +3350,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mShadowColor = color;
// Will change text clip region
- if (mEditor != null) mEditor.invalidateTextDisplayList();
+ if (mEditor != null) {
+ mEditor.invalidateTextDisplayList();
+ mEditor.invalidateHandlesAndActionMode();
+ }
invalidate();
}
@@ -5406,8 +5405,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mTemporaryDetach = false;
-
if (mEditor != null) mEditor.onAttachedToWindow();
if (mPreDrawListenerDetached) {
@@ -8289,14 +8286,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
newSelEnd = Selection.getSelectionEnd(buf);
}
- if (newSelStart == newSelEnd && hasTransientState()) {
- setHasTransientState(false);
- } else if (newSelStart != newSelEnd && !hasTransientState()) {
- setHasTransientState(true);
- }
-
if (mEditor != null) {
mEditor.refreshTextActionMode();
+ if (!hasSelection() && mEditor.mTextActionMode == null && hasTransientState()) {
+ // User generated selection has been removed.
+ setHasTransientState(false);
+ }
}
onSelectionChanged(newSelStart, newSelEnd);
}
@@ -8314,6 +8309,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mEditor != null) {
if (oldStart >= 0) mEditor.invalidateTextDisplayList(mLayout, oldStart, oldEnd);
if (newStart >= 0) mEditor.invalidateTextDisplayList(mLayout, newStart, newEnd);
+ mEditor.invalidateHandlesAndActionMode();
}
}
@@ -8368,40 +8364,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- /**
- * @hide
- */
- @Override
- public void dispatchFinishTemporaryDetach() {
- mDispatchTemporaryDetach = true;
- super.dispatchFinishTemporaryDetach();
- mDispatchTemporaryDetach = false;
- }
-
- @Override
- public void onStartTemporaryDetach() {
- super.onStartTemporaryDetach();
- // Only track when onStartTemporaryDetach() is called directly,
- // usually because this instance is an editable field in a list
- if (!mDispatchTemporaryDetach) mTemporaryDetach = true;
-
- // Tell the editor that we are temporarily detached. It can use this to preserve
- // selection state as needed.
- if (mEditor != null) mEditor.mTemporaryDetach = true;
- }
-
- @Override
- public void onFinishTemporaryDetach() {
- super.onFinishTemporaryDetach();
- // Only track when onStartTemporaryDetach() is called directly,
- // usually because this instance is an editable field in a list
- if (!mDispatchTemporaryDetach) mTemporaryDetach = false;
- if (mEditor != null) mEditor.mTemporaryDetach = false;
- }
-
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- if (mTemporaryDetach) {
+ if (isTemporarilyDetached()) {
// If we are temporarily in the detach state, then do nothing.
super.onFocusChanged(focused, direction, previouslyFocusedRect);
return;
@@ -9096,6 +9061,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mBufferType == BufferType.EDITABLE) {
info.setEditable(true);
+ if (isEnabled()) {
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT);
+ }
}
if (mEditor != null) {
@@ -9227,6 +9195,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
} return false;
+ case AccessibilityNodeInfo.ACTION_SET_TEXT: {
+ if (!isEnabled() || (mBufferType != BufferType.EDITABLE)) {
+ return false;
+ }
+ CharSequence text = (arguments != null) ? arguments.getCharSequence(
+ AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;
+ setText(text);
+ if (text != null && text.length() > 0) {
+ Selection.setSelection((Spannable) mText, text.length());
+ }
+ } return true;
default: {
return super.performAccessibilityActionInternal(action, arguments);
}
@@ -9235,52 +9214,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private boolean performAccessibilityActionClick(Bundle arguments) {
boolean handled = false;
- boolean processed = false;
if (!isEnabled()) {
return false;
}
- if (arguments != null && arguments.containsKey(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT)) {
- int spanIndex = arguments.getInt(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT, -1);
- if (spanIndex >= 0 && hasSpannableText()) {
- ClickableSpan[] spans = ((Spannable) mText).getSpans(0,
- mText.length(), ClickableSpan.class);
- if (spans != null && spans.length > spanIndex && spans[spanIndex] != null) {
- // Simulate View.onTouchEvent for an ACTION_UP event
- if (isFocusable() && !isFocused()) {
- requestFocus();
- }
- spans[spanIndex].onClick(this);
- handled = true;
- }
- }
- processed = true;
- }
-
- if (!processed && arguments != null && arguments.containsKey(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT)) {
- int characterIndex = arguments.getInt(
- AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT, -1);
- if (characterIndex >= 0 && hasSpannableText()) {
- ClickableSpan[] spans = ((Spannable) mText).getSpans(characterIndex,
- characterIndex, ClickableSpan.class);
- // click only on the first span to keep parity with onTouch() implementation
- if (spans != null && spans.length > 0 && spans[0] != null) {
- // Simulate View.onTouchEvent for an ACTION_UP event
- if (isFocusable() && !isFocused()) {
- requestFocus();
- }
- spans[0].onClick(this);
- handled = true;
- }
- }
- processed = true;
- }
-
- if (!processed && (isClickable() || isLongClickable())) {
+ if (isClickable() || isLongClickable()) {
// Simulate View.onTouchEvent for an ACTION_UP event
if (isFocusable() && !isFocused()) {
requestFocus();
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 5b0a90adde33..9cdb73ae51ce 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StyleRes;
+import android.annotation.TestApi;
import android.app.ActionBar;
import android.content.Context;
import android.content.res.TypedArray;
@@ -976,6 +977,15 @@ public class Toolbar extends ViewGroup {
}
/**
+ * @hide
+ */
+ @Nullable
+ @TestApi
+ public View getNavigationView() {
+ return mNavButtonView;
+ }
+
+ /**
* Return the Menu shown in the toolbar.
*
* <p>Applications that wish to populate the toolbar's menu can do so from here. To use
diff --git a/core/java/com/android/internal/app/procstats/SparseMappingTable.java b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
index 64c49a2bc80d..725227610c88 100644
--- a/core/java/com/android/internal/app/procstats/SparseMappingTable.java
+++ b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
@@ -28,7 +28,7 @@ import com.android.internal.util.GrowingArrayUtils;
/**
* Class that contains a set of tables mapping byte ids to long values.
- *
+ *
* This class is used to store the ProcessStats data. This data happens to be
* a set of very sparse tables, that is mostly append or overwrite, with infrequent
* resets of the data.
@@ -59,11 +59,11 @@ public class SparseMappingTable {
// Where the "index into array" part of the data appears in an offset integer.
private static final int INDEX_SHIFT = 16;
private static final int INDEX_MASK = 0xffff;
-
+
private int mSequence;
private int mNextIndex;
private final ArrayList<long[]> mLongs = new ArrayList<long[]>();
-
+
/**
* A table of data as stored in a SparseMappingTable.
*/
@@ -377,20 +377,24 @@ public class SparseMappingTable {
// since we were created or reset.
if (mSequence == UNINITIALIZED_SEQUENCE) {
logOrThrow("mSequence == UNINITIALIZED_SEQUENCE in"
- + " SparseMappingTable.Table. mParent.mSequence=" + mParent.mSequence);
+ + " SparseMappingTable.Table. -- "
+ + dumpInternalState());
+ return;
}
// Assert that our sequence number matches mParent's. If it isn't that means
- // we have been reset and our
+ // we have been reset and our
if (mSequence != mParent.mSequence) {
if (mSequence < mParent.mSequence) {
logOrThrow("Sequence mismatch. SparseMappingTable.resetTable()"
+ " called but not Table.resetTable() -- "
+ dumpInternalState());
+ return;
} else if (mSequence > mParent.mSequence) {
logOrThrow("Sequence mismatch. Table.resetTable()"
+ " called but not SparseMappingTable.resetTable() -- "
+ dumpInternalState());
+ return;
}
}
}
@@ -423,7 +427,7 @@ public class SparseMappingTable {
/**
* Check that all the keys are valid locations in the long arrays.
- *
+ *
* If any aren't, log it and return false. Else return true.
*/
private boolean validateKeys(boolean log) {
@@ -580,7 +584,7 @@ public class SparseMappingTable {
i++;
}
}
-
+
/**
* Extract the id from a key.
*/
@@ -611,7 +615,7 @@ public class SparseMappingTable {
* this is a debug build.)
*/
private static void logOrThrow(String message) {
- logOrThrow(message, null);
+ logOrThrow(message, new RuntimeException("Stack trace"));
}
/**
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 5a195cb7dd20..4260e50a31f2 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -33,8 +33,8 @@ interface IAppWidgetService {
//
// for AppWidgetHost
//
- int[] startListening(IAppWidgetHost host, String callingPackage, int hostId,
- out List<RemoteViews> updatedViews);
+ ParceledListSlice startListening(IAppWidgetHost host, String callingPackage, int hostId,
+ in int[] appWidgetIds, out int[] updatedIds);
void stopListening(String callingPackage, int hostId);
int allocateAppWidgetId(String callingPackage, int hostId);
void deleteAppWidgetId(String callingPackage, int appWidgetId);
diff --git a/core/java/com/android/internal/os/BackgroundThread.java b/core/java/com/android/internal/os/BackgroundThread.java
index d6f7b20189a8..cffba0177d14 100644
--- a/core/java/com/android/internal/os/BackgroundThread.java
+++ b/core/java/com/android/internal/os/BackgroundThread.java
@@ -18,6 +18,7 @@ package com.android.internal.os;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Trace;
/**
* Shared singleton background thread for each process.
@@ -34,6 +35,7 @@ public final class BackgroundThread extends HandlerThread {
if (sInstance == null) {
sInstance = new BackgroundThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 14ebe227f3b4..79138b7b3fbd 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -85,6 +85,7 @@ public class PowerProfile {
public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle";
public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx";
public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx";
+ public static final String POWER_WIFI_CONTROLLER_TX_LEVELS = "wifi.controller.tx_levels";
public static final String POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE = "wifi.controller.voltage";
public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle";
@@ -287,9 +288,15 @@ public class PowerProfile {
};
for (int i = 0; i < configResIds.length; i++) {
+ String key = configResIdKeys[i];
+ // if we already have some of these parameters in power_profile.xml, ignore the
+ // value in config.xml
+ if ((sPowerMap.containsKey(key) && (Double) sPowerMap.get(key) > 0)) {
+ continue;
+ }
int value = resources.getInteger(configResIds[i]);
if (value > 0) {
- sPowerMap.put(configResIdKeys[i], (double) value);
+ sPowerMap.put(key, (double) value);
}
}
}
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index e330de24f6d6..171a264eea8b 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -50,9 +50,12 @@ oneway interface IKeyguardService {
* Called when the device has finished going to sleep.
*
* @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN},
- * or {@link #OFF_BECAUSE_OF_TIMEOUT}.
+ * or {@link #OFF_BECAUSE_OF_TIMEOUT}.
+ * @param cameraGestureTriggered whether the camera gesture was triggered between
+ * {@link #onStartedGoingToSleep} and this method; if it's been
+ * triggered, we shouldn't lock the device.
*/
- void onFinishedGoingToSleep(int reason);
+ void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered);
/**
* Called when the device has started waking up.
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index d80b63acb90f..0f257d78d5f5 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -24,6 +24,7 @@ import android.app.ActivityManagerNative;
import android.app.SearchManager;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.IRotationWatcher.Stub;
@@ -514,6 +515,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mDecorContentParent.setWindowTitle(title);
}
mTitle = title;
+ WindowManager.LayoutParams params = getAttributes();
+ if (!TextUtils.equals(title, params.getTitle())) {
+ params.setTitle(title);
+ dispatchWindowAttributesChanged(getAttributes());
+ }
}
@Override
diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java
index 7a040801a9a5..3c1d2d6ce581 100644
--- a/core/java/com/android/internal/util/FastXmlSerializer.java
+++ b/core/java/com/android/internal/util/FastXmlSerializer.java
@@ -28,6 +28,7 @@ import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
@@ -38,14 +39,14 @@ import java.nio.charset.UnsupportedCharsetException;
*/
public class FastXmlSerializer implements XmlSerializer {
private static final String ESCAPE_TABLE[] = new String[] {
- null, null, null, null, null, null, null, null, // 0-7
- null, null, null, null, null, null, null, null, // 8-15
- null, null, null, null, null, null, null, null, // 16-23
- null, null, null, null, null, null, null, null, // 24-31
- null, null, "&quot;", null, null, null, "&amp;", null, // 32-39
- null, null, null, null, null, null, null, null, // 40-47
- null, null, null, null, null, null, null, null, // 48-55
- null, null, null, null, "&lt;", null, "&gt;", null, // 56-63
+ "&#0;", "&#1;", "&#2;", "&#3;", "&#4;", "&#5;", "&#6;", "&#7;", // 0-7
+ "&#8;", "&#9;", "&#10;", "&#11;", "&#12;", "&#13;", "&#14;", "&#15;", // 8-15
+ "&#16;", "&#17;", "&#18;", "&#19;", "&#20;", "&#21;", "&#22;", "&#23;", // 16-23
+ "&#24;", "&#25;", "&#26;", "&#27;", "&#28;", "&#29;", "&#30;", "&#31;", // 24-31
+ null, null, "&quot;", null, null, null, "&amp;", null, // 32-39
+ null, null, null, null, null, null, null, null, // 40-47
+ null, null, null, null, null, null, null, null, // 48-55
+ null, null, null, null, "&lt;", null, "&gt;", null, // 56-63
};
private static final int BUFFER_LEN = 8192;
@@ -310,7 +311,9 @@ public class FastXmlSerializer implements XmlSerializer {
throw new IllegalArgumentException();
if (true) {
try {
- mCharset = Charset.forName(encoding).newEncoder();
+ mCharset = Charset.forName(encoding).newEncoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
} catch (IllegalCharsetNameException e) {
throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
encoding).initCause(e));
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index da223a64e2e8..1848fe88dea9 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1460,6 +1460,7 @@ public final class FloatingToolbar {
super(Preconditions.checkNotNull(popup).mContext);
this.mPopup = popup;
setScrollBarDefaultDelayBeforeFade(ViewConfiguration.getScrollDefaultDelay() * 3);
+ setScrollIndicators(View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
}
@Override
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index b07e36adfdf7..21c4d1235042 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -33,9 +33,12 @@ interface ILockSettings {
void setLockPassword(in String password, in String savedPassword, int userId);
VerifyCredentialResponse checkPassword(in String password, int userId);
VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId);
+ VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId);
boolean checkVoldPassword(int userId);
boolean havePattern(int userId);
boolean havePassword(int userId);
+ void setSeparateProfileChallengeEnabled(int userId, boolean enabled, String managedUserPassword);
+ boolean getSeparateProfileChallengeEnabled(int userId);
void registerStrongAuthTracker(in IStrongAuthTracker tracker);
void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
void requireStrongAuth(int strongAuthReason, int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 4880664f1e7f..713f56f46266 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -145,6 +145,43 @@ public final class LockPatternChecker {
}
/**
+ * Verify a password asynchronously.
+ *
+ * @param utils The LockPatternUtils instance to use.
+ * @param password The password to check.
+ * @param challenge The challenge to verify against the pattern.
+ * @param userId The user to check against the pattern.
+ * @param callback The callback to be invoked with the verification result.
+ */
+ public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
+ final String password,
+ final boolean isPattern,
+ final long challenge,
+ final int userId,
+ final OnVerifyCallback callback) {
+ AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
+ private int mThrottleTimeout;
+
+ @Override
+ protected byte[] doInBackground(Void... args) {
+ try {
+ return utils.verifyTiedProfileChallenge(password, isPattern, challenge, userId);
+ } catch (RequestThrottledException ex) {
+ mThrottleTimeout = ex.getTimeoutMs();
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(byte[] result) {
+ callback.onVerified(result, mThrottleTimeout);
+ }
+ };
+ task.execute();
+ return task;
+ }
+
+ /**
* Checks a password asynchronously.
*
* @param utils The LockPatternUtils instance to use.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 3d892afbb5f3..bceeaca8e343 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -137,8 +137,6 @@ public class LockPatternUtils {
private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged";
- private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
-
// Maximum allowed number of repeated or ordered characters in a sequence before we'll
// consider it a complex PIN/password.
public static final int MAX_ALLOWED_SEQUENCE = 3;
@@ -377,6 +375,36 @@ public class LockPatternUtils {
}
}
+
+ /**
+ * Check to see if a password matches the saved password.
+ * If password matches, return an opaque attestation that the challenge
+ * was verified.
+ *
+ * @param password The password to check.
+ * @param challenge The challenge to verify against the password
+ * @return the attestation that the challenge was verified, or null.
+ */
+ public byte[] verifyTiedProfileChallenge(String password, boolean isPattern, long challenge,
+ int userId) throws RequestThrottledException {
+ throwIfCalledOnMainThread();
+ try {
+ VerifyCredentialResponse response =
+ getLockSettings().verifyTiedProfileChallenge(password, isPattern, challenge,
+ userId);
+
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+ return response.getPayload();
+ } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+ throw new RequestThrottledException(response.getTimeout());
+ } else {
+ return null;
+ }
+ } catch (RemoteException re) {
+ return null;
+ }
+ }
+
/**
* Check to see if a password matches the saved password. If no password exists,
* always returns true.
@@ -785,6 +813,7 @@ public class LockPatternUtils {
}
getLockSettings().setLockPassword(password, savedPassword, userHandle);
+ getLockSettings().setSeparateProfileChallengeEnabled(userHandle, true, null);
int computedQuality = computePasswordQuality(password);
// Update the device encryption password.
@@ -919,11 +948,23 @@ public class LockPatternUtils {
/**
* Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
* for user handles that do not belong to a managed profile.
+ *
+ * @param userHandle Managed profile user id
+ * @param enabled True if separate challenge is enabled
+ * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
+ * true
*/
- public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled) {
+ public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
+ String managedUserPassword) {
UserInfo info = getUserManager().getUserInfo(userHandle);
if (info.isManagedProfile()) {
- setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userHandle);
+ try {
+ getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
+ managedUserPassword);
+ onAfterChangingPassword(userHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't update work profile challenge enabled");
+ }
}
}
@@ -935,7 +976,13 @@ public class LockPatternUtils {
if (info == null || !info.isManagedProfile()) {
return false;
}
- return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userHandle);
+ try {
+ return getLockSettings().getSeparateProfileChallengeEnabled(userHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get separate profile challenge enabled");
+ // Default value is false
+ return false;
+ }
}
/**
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index c4347f832bd5..25b487efdae6 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -17,9 +17,14 @@
package com.android.internal.widget;
+import android.annotation.NonNull;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -85,6 +90,10 @@ public class ResolverDrawerLayout extends ViewGroup {
private final float mMinFlingVelocity;
private final OverScroller mScroller;
private final VelocityTracker mVelocityTracker;
+ private final Drawable mScrollIndicatorDrawable;
+ private final Drawable mFakeForeground;
+
+ private View mButtonBar;
private OnDismissedListener mOnDismissedListener;
private RunOnDismissedListener mRunOnDismissedListener;
@@ -106,6 +115,8 @@ public class ResolverDrawerLayout extends ViewGroup {
}
};
+ private final int[] mTempOffset = new int[2];
+
public ResolverDrawerLayout(Context context) {
this(context, null);
}
@@ -127,6 +138,9 @@ public class ResolverDrawerLayout extends ViewGroup {
mMaxCollapsedHeight);
a.recycle();
+ mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
+ mFakeForeground = new ColorDrawable(Color.TRANSPARENT);
+
mScroller = new OverScroller(context, AnimationUtils.loadInterpolator(context,
android.R.interpolator.decelerate_quint));
mVelocityTracker = VelocityTracker.obtain();
@@ -138,6 +152,13 @@ public class ResolverDrawerLayout extends ViewGroup {
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mButtonBar = findViewById(R.id.button_bar);
+ }
+
public void setSmallCollapsed(boolean smallCollapsed) {
mSmallCollapsed = smallCollapsed;
requestLayout();
@@ -202,8 +223,7 @@ public class ResolverDrawerLayout extends ViewGroup {
}
final boolean isCollapsedNew = mCollapseOffset != 0;
if (isCollapsedOld != isCollapsedNew) {
- notifyViewAccessibilityStateChangedIfNeeded(
- AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+ onCollapsedChanged(isCollapsedNew);
}
} else {
// Start out collapsed at first unless we restored state for otherwise
@@ -442,8 +462,7 @@ public class ResolverDrawerLayout extends ViewGroup {
mTopOffset += dy;
final boolean isCollapsedNew = newPos != 0;
if (isCollapsedOld != isCollapsedNew) {
- notifyViewAccessibilityStateChangedIfNeeded(
- AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+ onCollapsedChanged(isCollapsedNew);
}
postInvalidateOnAnimation();
return dy;
@@ -451,6 +470,14 @@ public class ResolverDrawerLayout extends ViewGroup {
return 0;
}
+ private void onCollapsedChanged(boolean isCollapsed) {
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+
+ // Set a fake foreground so that we receive onDrawForeground().
+ setForeground(isCollapsed ? mFakeForeground : null);
+ }
+
void dispatchOnDismissed() {
if (mOnDismissedListener != null) {
mOnDismissedListener.onDismissed();
@@ -709,6 +736,23 @@ public class ResolverDrawerLayout extends ViewGroup {
}
@Override
+ public void onDrawForeground(Canvas canvas) {
+ if (isCollapsed() && mButtonBar != null) {
+ // Draw the scroll indicator directly above the button bar.
+ final int height = mScrollIndicatorDrawable.getIntrinsicHeight();
+ mButtonBar.getLocationInWindow(mTempOffset);
+ final int barTop = mTempOffset[1];
+ getLocationInWindow(mTempOffset);
+ final int myTop = mTempOffset[1];
+ final int top = (barTop - myTop) - height;
+ mScrollIndicatorDrawable.setBounds(0, top, getWidth(), top + height);
+ mScrollIndicatorDrawable.draw(canvas);
+ }
+
+ super.onDrawForeground(canvas);
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int sourceWidth = MeasureSpec.getSize(widthMeasureSpec);
int widthSize = sourceWidth;
diff --git a/core/java/com/android/server/net/NetlinkTracker.java b/core/java/com/android/server/net/NetlinkTracker.java
index d45982eff8ba..5b421d988e0a 100644
--- a/core/java/com/android/server/net/NetlinkTracker.java
+++ b/core/java/com/android/server/net/NetlinkTracker.java
@@ -102,6 +102,19 @@ public class NetlinkTracker extends BaseNetworkObserver {
}
@Override
+ public void interfaceRemoved(String iface) {
+ maybeLog("interfaceRemoved", iface);
+ if (mInterfaceName.equals(iface)) {
+ // Our interface was removed. Clear our LinkProperties and tell our owner that they are
+ // now empty. Note that from the moment that the interface is removed, any further
+ // interface-specific messages (e.g., RTM_DELADDR) will not reach us, because the netd
+ // code that parses them will not be able to resolve the ifindex to an interface name.
+ clearLinkProperties();
+ mCallback.update();
+ }
+ }
+
+ @Override
public void addressUpdated(String iface, LinkAddress address) {
if (mInterfaceName.equals(iface)) {
maybeLog("addressUpdated", iface, address);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index c6112d971abe..8a512a6df06b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -103,7 +103,6 @@ LOCAL_SRC_FILES:= \
android_util_jar_StrictJarFile.cpp \
android_graphics_Canvas.cpp \
android_graphics_Picture.cpp \
- android/graphics/AvoidXfermode.cpp \
android/graphics/Bitmap.cpp \
android/graphics/BitmapFactory.cpp \
android/graphics/Camera.cpp \
diff --git a/core/jni/android/graphics/AvoidXfermode.cpp b/core/jni/android/graphics/AvoidXfermode.cpp
deleted file mode 100644
index 9ca1f26e3ab0..000000000000
--- a/core/jni/android/graphics/AvoidXfermode.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "AvoidXfermode.h"
-#include "SkColorPriv.h"
-#include "SkReadBuffer.h"
-#include "SkWriteBuffer.h"
-#include "SkString.h"
-
-AvoidXfermode::AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) {
- if (tolerance > 255) {
- tolerance = 255;
- }
- fTolerance = SkToU8(tolerance);
- fOpColor = opColor;
- fDistMul = (256 << 14) / (tolerance + 1);
- fMode = mode;
-}
-
-SkFlattenable* AvoidXfermode::CreateProc(SkReadBuffer& buffer) {
- const SkColor color = buffer.readColor();
- const unsigned tolerance = buffer.readUInt();
- const unsigned mode = buffer.readUInt();
- return Create(color, tolerance, (Mode)mode);
-}
-
-void AvoidXfermode::flatten(SkWriteBuffer& buffer) const {
- buffer.writeColor(fOpColor);
- buffer.writeUInt(fTolerance);
- buffer.writeUInt(fMode);
-}
-
-// returns 0..31
-static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) {
- SkASSERT(r <= SK_R16_MASK);
- SkASSERT(g <= SK_G16_MASK);
- SkASSERT(b <= SK_B16_MASK);
-
- unsigned dr = SkAbs32(SkGetPackedR16(c) - r);
- unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS);
- unsigned db = SkAbs32(SkGetPackedB16(c) - b);
-
- return SkMax32(dr, SkMax32(dg, db));
-}
-
-// returns 0..255
-static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) {
- SkASSERT(r <= 0xFF);
- SkASSERT(g <= 0xFF);
- SkASSERT(b <= 0xFF);
-
- unsigned dr = SkAbs32(SkGetPackedR32(c) - r);
- unsigned dg = SkAbs32(SkGetPackedG32(c) - g);
- unsigned db = SkAbs32(SkGetPackedB32(c) - b);
-
- return SkMax32(dr, SkMax32(dg, db));
-}
-
-static int scale_dist_14(int dist, uint32_t mul, uint32_t sub) {
- int tmp = dist * mul - sub;
- int result = (tmp + (1 << 13)) >> 14;
-
- return result;
-}
-
-static inline unsigned Accurate255To256(unsigned x) {
- return x + (x >> 7);
-}
-
-void AvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
- const SkAlpha aa[]) const {
- unsigned opR = SkColorGetR(fOpColor);
- unsigned opG = SkColorGetG(fOpColor);
- unsigned opB = SkColorGetB(fOpColor);
- uint32_t mul = fDistMul;
- uint32_t sub = (fDistMul - (1 << 14)) << 8;
-
- int MAX, mask;
-
- if (kTargetColor_Mode == fMode) {
- mask = -1;
- MAX = 255;
- } else {
- mask = 0;
- MAX = 0;
- }
-
- for (int i = 0; i < count; i++) {
- int d = color_dist32(dst[i], opR, opG, opB);
- // now reverse d if we need to
- d = MAX + (d ^ mask) - mask;
- SkASSERT((unsigned)d <= 255);
- d = Accurate255To256(d);
-
- d = scale_dist_14(d, mul, sub);
- SkASSERT(d <= 256);
-
- if (d > 0) {
- if (aa) {
- d = SkAlphaMul(d, Accurate255To256(*aa++));
- if (0 == d) {
- continue;
- }
- }
- dst[i] = SkFourByteInterp256(src[i], dst[i], d);
- }
- }
-}
-
-static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) {
- SkASSERT(scale <= 32);
- scale <<= 3;
-
- return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale),
- SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale),
- SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale));
-}
-
-void AvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
- const SkAlpha aa[]) const {
- unsigned opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS);
- unsigned opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS);
- unsigned opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS);
- uint32_t mul = fDistMul;
- uint32_t sub = (fDistMul - (1 << 14)) << SK_R16_BITS;
-
- int MAX, mask;
-
- if (kTargetColor_Mode == fMode) {
- mask = -1;
- MAX = 31;
- } else {
- mask = 0;
- MAX = 0;
- }
-
- for (int i = 0; i < count; i++) {
- int d = color_dist16(dst[i], opR, opG, opB);
- // now reverse d if we need to
- d = MAX + (d ^ mask) - mask;
- SkASSERT((unsigned)d <= 31);
- // convert from 0..31 to 0..32
- d += d >> 4;
- d = scale_dist_14(d, mul, sub);
- SkASSERT(d <= 32);
-
- if (d > 0) {
- if (aa) {
- d = SkAlphaMul(d, Accurate255To256(*aa++));
- if (0 == d) {
- continue;
- }
- }
- dst[i] = SkBlend3216(src[i], dst[i], d);
- }
- }
-}
-
-void AvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
- const SkAlpha aa[]) const {
-}
-
-#ifndef SK_IGNORE_TO_STRING
-void AvoidXfermode::toString(SkString* str) const {
- str->append("AvoidXfermode: opColor: ");
- str->appendHex(fOpColor);
- str->appendf("distMul: %d ", fDistMul);
-
- static const char* gModeStrings[] = { "Avoid", "Target" };
-
- str->appendf("mode: %s", gModeStrings[fMode]);
-}
-#endif
diff --git a/core/jni/android/graphics/AvoidXfermode.h b/core/jni/android/graphics/AvoidXfermode.h
deleted file mode 100644
index 8b7fb7165133..000000000000
--- a/core/jni/android/graphics/AvoidXfermode.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef AvoidXfermode_DEFINED
-#define AvoidXfermode_DEFINED
-
-#include "SkColor.h"
-#include "SkTypes.h"
-#include "SkXfermode.h"
-
-/** \class AvoidXfermode
-
- This xfermode will draw the src everywhere except on top of the specified
- color.
-*/
-class AvoidXfermode : public SkXfermode {
-public:
- enum Mode {
- kAvoidColor_Mode, //!< draw everywhere except on the opColor
- kTargetColor_Mode //!< draw only on top of the opColor
- };
-
- /** This xfermode draws, or doesn't draw, based on the destination's
- distance from an op-color.
-
- There are two modes, and each mode interprets a tolerance value.
-
- Avoid: In this mode, drawing is allowed only on destination pixels that
- are different from the op-color.
- Tolerance near 0: avoid any colors even remotely similar to the op-color
- Tolerance near 255: avoid only colors nearly identical to the op-color
-
- Target: In this mode, drawing only occurs on destination pixels that
- are similar to the op-color
- Tolerance near 0: draw only on colors that are nearly identical to the op-color
- Tolerance near 255: draw on any colors even remotely similar to the op-color
- */
- static AvoidXfermode* Create(SkColor opColor, U8CPU tolerance, Mode mode) {
- return new AvoidXfermode(opColor, tolerance, mode);
- }
-
- // overrides from SkXfermode
- void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
- const SkAlpha aa[]) const override;
- void xfer16(uint16_t dst[], const SkPMColor src[], int count,
- const SkAlpha aa[]) const override;
- void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
- const SkAlpha aa[]) const override;
-
- SK_TO_STRING_OVERRIDE()
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(AvoidXfermode)
-
-protected:
- AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode);
- void flatten(SkWriteBuffer&) const override;
-
-private:
- SkColor fOpColor;
- uint32_t fDistMul; // x.14 cached from fTolerance
- uint8_t fTolerance;
- Mode fMode;
-
- typedef SkXfermode INHERITED;
-};
-
-#endif
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 1844a9870ada..f46f45cc5e5d 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -768,6 +768,22 @@ namespace PaintGlue {
return false;
}
+ // Returns true if the given string is exact one pair of regional indicators.
+ static bool isFlag(const jchar* str, size_t length) {
+ const jchar RI_LEAD_SURROGATE = 0xD83C;
+ const jchar RI_TRAIL_SURROGATE_MIN = 0xDDE6;
+ const jchar RI_TRAIL_SURROGATE_MAX = 0xDDFF;
+
+ if (length != 4) {
+ return false;
+ }
+ if (str[0] != RI_LEAD_SURROGATE || str[2] != RI_LEAD_SURROGATE) {
+ return false;
+ }
+ return RI_TRAIL_SURROGATE_MIN <= str[1] && str[1] <= RI_TRAIL_SURROGATE_MAX &&
+ RI_TRAIL_SURROGATE_MIN <= str[3] && str[3] <= RI_TRAIL_SURROGATE_MAX;
+ }
+
static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
jint bidiFlags, jstring string) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
@@ -817,7 +833,26 @@ namespace PaintGlue {
// in joining scripts, such as Arabic and Mongolian.
return false;
}
- return nGlyphs > 0 && !layoutContainsNotdef(layout);
+
+ if (nGlyphs == 0 || layoutContainsNotdef(layout)) {
+ return false; // The collection doesn't have a glyph.
+ }
+
+ if (nChars == 2 && isFlag(str.get(), str.size())) {
+ // Some font may have a special glyph for unsupported regional indicator pairs.
+ // To return false for this case, need to compare the glyph id with the one of ZZ
+ // since ZZ is reserved for unknown or invalid territory.
+ // U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16.
+ static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF };
+ Layout zzLayout;
+ MinikinUtils::doLayout(&zzLayout, paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
+ if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) {
+ // The font collection doesn't have a glyph for unknown flag. Just return true.
+ return true;
+ }
+ return zzLayout.getGlyphId(0) != layout.getGlyphId(0);
+ }
+ return true;
}
static jfloat doRunAdvance(const Paint* paint, Typeface* typeface, const jchar buf[],
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2018e76e9bee..6e9830ec3852 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -65,12 +65,12 @@ static bool isProtectedContext() {
EGLContext ctx = eglGetCurrentContext();
if (dpy == EGL_NO_DISPLAY) {
- ALOGE("isProtectedSurface: invalid current EGLDisplay");
+ ALOGI("isProtectedSurface: invalid current EGLDisplay");
return false;
}
if (ctx == EGL_NO_CONTEXT) {
- ALOGE("isProtectedSurface: invalid current EGLContext");
+ ALOGI("isProtectedSurface: invalid current EGLContext");
return false;
}
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index a2662f9e81c7..b04293e0afa8 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "jni.h"
#include "GraphicsJNI.h"
+#include "jni.h"
#include "core_jni_helpers.h"
-#include "log/log.h"
+#include "PathParser.h"
#include "VectorDrawable.h"
#include <hwui/Paint.h>
@@ -27,26 +27,61 @@ namespace android {
using namespace uirenderer;
using namespace uirenderer::VectorDrawable;
+/**
+ * VectorDrawable's pre-draw construction.
+ */
static jlong createTree(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* rootGroup = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
VectorDrawable::Tree* tree = new VectorDrawable::Tree(rootGroup);
return reinterpret_cast<jlong>(tree);
}
-static void setTreeViewportSize(JNIEnv*, jobject, jlong treePtr,
- jfloat viewportWidth, jfloat viewportHeight) {
- VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
- tree->setViewportSize(viewportWidth, viewportHeight);
+static jlong createEmptyFullPath(JNIEnv*, jobject) {
+ VectorDrawable::FullPath* newPath = new VectorDrawable::FullPath();
+ return reinterpret_cast<jlong>(newPath);
}
-static jboolean setRootAlpha(JNIEnv*, jobject, jlong treePtr, jfloat alpha) {
- VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
- return tree->setRootAlpha(alpha);
+static jlong createFullPath(JNIEnv*, jobject, jlong srcFullPathPtr) {
+ VectorDrawable::FullPath* srcFullPath =
+ reinterpret_cast<VectorDrawable::FullPath*>(srcFullPathPtr);
+ VectorDrawable::FullPath* newPath = new VectorDrawable::FullPath(*srcFullPath);
+ return reinterpret_cast<jlong>(newPath);
}
-static jfloat getRootAlpha(JNIEnv*, jobject, jlong treePtr) {
- VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
- return tree->getRootAlpha();
+static jlong createEmptyClipPath(JNIEnv*, jobject) {
+ VectorDrawable::ClipPath* newPath = new VectorDrawable::ClipPath();
+ return reinterpret_cast<jlong>(newPath);
+}
+
+static jlong createClipPath(JNIEnv*, jobject, jlong srcClipPathPtr) {
+ VectorDrawable::ClipPath* srcClipPath =
+ reinterpret_cast<VectorDrawable::ClipPath*>(srcClipPathPtr);
+ VectorDrawable::ClipPath* newPath = new VectorDrawable::ClipPath(*srcClipPath);
+ return reinterpret_cast<jlong>(newPath);
+}
+
+static jlong createEmptyGroup(JNIEnv*, jobject) {
+ VectorDrawable::Group* newGroup = new VectorDrawable::Group();
+ return reinterpret_cast<jlong>(newGroup);
+}
+
+static jlong createGroup(JNIEnv*, jobject, jlong srcGroupPtr) {
+ VectorDrawable::Group* srcGroup = reinterpret_cast<VectorDrawable::Group*>(srcGroupPtr);
+ VectorDrawable::Group* newGroup = new VectorDrawable::Group(*srcGroup);
+ return reinterpret_cast<jlong>(newGroup);
+}
+
+static void setNodeName(JNIEnv* env, jobject, jlong nodePtr, jstring nameStr) {
+ VectorDrawable::Node* node = reinterpret_cast<VectorDrawable::Node*>(nodePtr);
+ const char* nodeName = env->GetStringUTFChars(nameStr, NULL);
+ node->setName(nodeName);
+ env->ReleaseStringUTFChars(nameStr, nodeName);
+}
+
+static void addChild(JNIEnv*, jobject, jlong groupPtr, jlong childPtr) {
+ VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
+ VectorDrawable::Node* child = reinterpret_cast<VectorDrawable::Node*>(childPtr);
+ group->addChild(child);
}
static void setAllowCaching(JNIEnv*, jobject, jlong treePtr, jboolean allowCaching) {
@@ -54,6 +89,9 @@ static void setAllowCaching(JNIEnv*, jobject, jlong treePtr, jboolean allowCachi
tree->setAllowCaching(allowCaching);
}
+/**
+ * Draw
+ */
static void draw(JNIEnv* env, jobject, jlong treePtr, jlong canvasPtr,
jlong colorFilterPtr, jobject jrect, jboolean needsMirroring, jboolean canReuseCache) {
VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
@@ -64,16 +102,23 @@ static void draw(JNIEnv* env, jobject, jlong treePtr, jlong canvasPtr,
tree->draw(canvas, colorFilter, rect, needsMirroring, canReuseCache);
}
-static jlong createEmptyFullPath(JNIEnv*, jobject) {
- VectorDrawable::FullPath* newPath = new VectorDrawable::FullPath();
- return reinterpret_cast<jlong>(newPath);
+/**
+ * Setters and getters for updating staging properties that can happen both pre-draw and post draw.
+ */
+static void setTreeViewportSize(JNIEnv*, jobject, jlong treePtr,
+ jfloat viewportWidth, jfloat viewportHeight) {
+ VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+ tree->mutateStagingProperties()->setViewportSize(viewportWidth, viewportHeight);
}
-static jlong createFullPath(JNIEnv*, jobject, jlong srcFullPathPtr) {
- VectorDrawable::FullPath* srcFullPath =
- reinterpret_cast<VectorDrawable::FullPath*>(srcFullPathPtr);
- VectorDrawable::FullPath* newPath = new VectorDrawable::FullPath(*srcFullPath);
- return reinterpret_cast<jlong>(newPath);
+static jboolean setRootAlpha(JNIEnv*, jobject, jlong treePtr, jfloat alpha) {
+ VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+ return tree->mutateStagingProperties()->setRootAlpha(alpha);
+}
+
+static jfloat getRootAlpha(JNIEnv*, jobject, jlong treePtr) {
+ VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+ return tree->stagingProperties()->getRootAlpha();
}
static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
@@ -81,28 +126,28 @@ static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong full
jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit,
jint strokeLineCap, jint strokeLineJoin, jint fillType) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha,
- trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap,
- strokeLineJoin, fillType);
+ fullPath->mutateStagingProperties()->updateProperties(strokeWidth, strokeColor, strokeAlpha,
+ fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit,
+ strokeLineCap, strokeLineJoin, fillType);
}
static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
SkShader* fillShader = reinterpret_cast<SkShader*>(fillGradientPtr);
- path->setFillGradient(fillShader);
+ path->mutateStagingProperties()->setFillGradient(fillShader);
}
static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) {
VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
SkShader* strokeShader = reinterpret_cast<SkShader*>(strokeGradientPtr);
- path->setStrokeGradient(strokeShader);
+ path->mutateStagingProperties()->setStrokeGradient(strokeShader);
}
static jboolean getFullPathProperties(JNIEnv* env, jobject, jlong fullPathPtr,
jbyteArray outProperties, jint length) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
int8_t pathProperties[length];
- bool success = fullPath->getProperties(pathProperties, length);
+ bool success = fullPath->stagingProperties()->copyProperties(pathProperties, length);
env->SetByteArrayRegion(outProperties, 0, length, reinterpret_cast<int8_t*>(&pathProperties));
return success;
}
@@ -111,215 +156,187 @@ static jboolean getGroupProperties(JNIEnv* env, jobject, jlong groupPtr,
jfloatArray outProperties, jint length) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
float groupProperties[length];
- bool success = group->getProperties(groupProperties, length);
+ bool success = group->stagingProperties()->copyProperties(groupProperties, length);
env->SetFloatArrayRegion(outProperties, 0, length, reinterpret_cast<float*>(&groupProperties));
return success;
}
-static jlong createEmptyClipPath(JNIEnv*, jobject) {
- VectorDrawable::ClipPath* newPath = new VectorDrawable::ClipPath();
- return reinterpret_cast<jlong>(newPath);
-}
-
-static jlong createClipPath(JNIEnv*, jobject, jlong srcClipPathPtr) {
- VectorDrawable::ClipPath* srcClipPath =
- reinterpret_cast<VectorDrawable::ClipPath*>(srcClipPathPtr);
- VectorDrawable::ClipPath* newPath = new VectorDrawable::ClipPath(*srcClipPath);
- return reinterpret_cast<jlong>(newPath);
-}
-
-static jlong createEmptyGroup(JNIEnv*, jobject) {
- VectorDrawable::Group* newGroup = new VectorDrawable::Group();
- return reinterpret_cast<jlong>(newGroup);
-}
-
-static jlong createGroup(JNIEnv*, jobject, jlong srcGroupPtr) {
- VectorDrawable::Group* srcGroup = reinterpret_cast<VectorDrawable::Group*>(srcGroupPtr);
- VectorDrawable::Group* newGroup = new VectorDrawable::Group(*srcGroup);
- return reinterpret_cast<jlong>(newGroup);
-}
-
-static void setNodeName(JNIEnv* env, jobject, jlong nodePtr, jstring nameStr) {
- VectorDrawable::Node* node = reinterpret_cast<VectorDrawable::Node*>(nodePtr);
- const char* nodeName = env->GetStringUTFChars(nameStr, NULL);
- node->setName(nodeName);
- env->ReleaseStringUTFChars(nameStr, nodeName);
-}
-
static void updateGroupProperties(JNIEnv*, jobject, jlong groupPtr, jfloat rotate, jfloat pivotX,
jfloat pivotY, jfloat scaleX, jfloat scaleY, jfloat translateX, jfloat translateY) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->updateLocalMatrix(rotate, pivotX, pivotY, scaleX, scaleY, translateX, translateY);
-}
-
-static void addChild(JNIEnv*, jobject, jlong groupPtr, jlong childPtr) {
- VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- VectorDrawable::Node* child = reinterpret_cast<VectorDrawable::Node*>(childPtr);
- group->addChild(child);
+ group->mutateStagingProperties()->updateProperties(rotate, pivotX, pivotY, scaleX, scaleY,
+ translateX, translateY);
}
static void setPathString(JNIEnv* env, jobject, jlong pathPtr, jstring inputStr,
jint stringLength) {
VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(pathPtr);
const char* pathString = env->GetStringUTFChars(inputStr, NULL);
- path->setPath(pathString, stringLength);
+
+ PathParser::ParseResult result;
+ PathData data;
+ PathParser::getPathDataFromString(&data, &result, pathString, stringLength);
+ path->mutateStagingProperties()->setData(data);
env->ReleaseStringUTFChars(inputStr, pathString);
}
+/**
+ * Setters and getters that should only be called from animation thread for animation purpose.
+ */
static jfloat getRotation(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- return group->getRotation();
+ return group->stagingProperties()->getRotation();
}
static void setRotation(JNIEnv*, jobject, jlong groupPtr, jfloat rotation) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->setRotation(rotation);
+ group->mutateStagingProperties()->setRotation(rotation);
}
static jfloat getPivotX(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- return group->getPivotX();
+ return group->stagingProperties()->getPivotX();
}
static void setPivotX(JNIEnv*, jobject, jlong groupPtr, jfloat pivotX) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->setPivotX(pivotX);
+ group->mutateStagingProperties()->setPivotX(pivotX);
}
static jfloat getPivotY(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- return group->getPivotY();
+ return group->stagingProperties()->getPivotY();
}
static void setPivotY(JNIEnv*, jobject, jlong groupPtr, jfloat pivotY) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->setPivotY(pivotY);
+ group->mutateStagingProperties()->setPivotY(pivotY);
}
static jfloat getScaleX(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- return group->getScaleX();
+ return group->stagingProperties()->getScaleX();
}
static void setScaleX(JNIEnv*, jobject, jlong groupPtr, jfloat scaleX) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->setScaleX(scaleX);
+ group->mutateStagingProperties()->setScaleX(scaleX);
}
static jfloat getScaleY(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- return group->getScaleY();
+ return group->stagingProperties()->getScaleY();
}
static void setScaleY(JNIEnv*, jobject, jlong groupPtr, jfloat scaleY) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->setScaleY(scaleY);
+ group->mutateStagingProperties()->setScaleY(scaleY);
}
static jfloat getTranslateX(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- return group->getTranslateX();
+ return group->stagingProperties()->getTranslateX();
}
static void setTranslateX(JNIEnv*, jobject, jlong groupPtr, jfloat translateX) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->setTranslateX(translateX);
+ group->mutateStagingProperties()->setTranslateX(translateX);
}
static jfloat getTranslateY(JNIEnv*, jobject, jlong groupPtr) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- return group->getTranslateY();
+ return group->stagingProperties()->getTranslateY();
}
static void setTranslateY(JNIEnv*, jobject, jlong groupPtr, jfloat translateY) {
VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
- group->setTranslateY(translateY);
+ group->mutateStagingProperties()->setTranslateY(translateY);
}
static void setPathData(JNIEnv*, jobject, jlong pathPtr, jlong pathDataPtr) {
VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(pathPtr);
PathData* pathData = reinterpret_cast<PathData*>(pathDataPtr);
- path->setPathData(*pathData);
+ path->mutateStagingProperties()->setData(*pathData);
}
static jfloat getStrokeWidth(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getStrokeWidth();
+ return fullPath->stagingProperties()->getStrokeWidth();
}
static void setStrokeWidth(JNIEnv*, jobject, jlong fullPathPtr, jfloat strokeWidth) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setStrokeWidth(strokeWidth);
+ fullPath->mutateStagingProperties()->setStrokeWidth(strokeWidth);
}
static jint getStrokeColor(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getStrokeColor();
+ return fullPath->stagingProperties()->getStrokeColor();
}
static void setStrokeColor(JNIEnv*, jobject, jlong fullPathPtr, jint strokeColor) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setStrokeColor(strokeColor);
+ fullPath->mutateStagingProperties()->setStrokeColor(strokeColor);
}
static jfloat getStrokeAlpha(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getStrokeAlpha();
+ return fullPath->stagingProperties()->getStrokeAlpha();
}
static void setStrokeAlpha(JNIEnv*, jobject, jlong fullPathPtr, jfloat strokeAlpha) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setStrokeAlpha(strokeAlpha);
+ fullPath->mutateStagingProperties()->setStrokeAlpha(strokeAlpha);
}
static jint getFillColor(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getFillColor();
+ return fullPath->stagingProperties()->getFillColor();
}
static void setFillColor(JNIEnv*, jobject, jlong fullPathPtr, jint fillColor) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setFillColor(fillColor);
+ fullPath->mutateStagingProperties()->setFillColor(fillColor);
}
static jfloat getFillAlpha(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getFillAlpha();
+ return fullPath->stagingProperties()->getFillAlpha();
}
static void setFillAlpha(JNIEnv*, jobject, jlong fullPathPtr, jfloat fillAlpha) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setFillAlpha(fillAlpha);
+ fullPath->mutateStagingProperties()->setFillAlpha(fillAlpha);
}
static jfloat getTrimPathStart(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getTrimPathStart();
+ return fullPath->stagingProperties()->getTrimPathStart();
}
static void setTrimPathStart(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPathStart) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setTrimPathStart(trimPathStart);
+ fullPath->mutateStagingProperties()->setTrimPathStart(trimPathStart);
}
static jfloat getTrimPathEnd(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getTrimPathEnd();
+ return fullPath->stagingProperties()->getTrimPathEnd();
}
static void setTrimPathEnd(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPathEnd) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setTrimPathEnd(trimPathEnd);
+ fullPath->mutateStagingProperties()->setTrimPathEnd(trimPathEnd);
}
static jfloat getTrimPathOffset(JNIEnv*, jobject, jlong fullPathPtr) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- return fullPath->getTrimPathOffset();
+ return fullPath->stagingProperties()->getTrimPathOffset();
}
static void setTrimPathOffset(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPathOffset) {
VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
- fullPath->setTrimPathOffset(trimPathOffset);
+ fullPath->mutateStagingProperties()->setTrimPathOffset(trimPathOffset);
}
static const JNINativeMethod gMethods[] = {
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 42dc983792d2..91a3b4f77052 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -33,7 +33,7 @@
#include "JNIHelp.h"
#include "core_jni_helpers.h"
-//static constexpr int OS_APP_ID=-1;
+static constexpr int OS_APP_ID=-1;
static constexpr int MIN_APP_ID=1;
static constexpr int MAX_APP_ID=128;
@@ -145,6 +145,14 @@ static int set_os_app_as_destination(hub_message_t *msg, int hubHandle) {
}
}
+static int get_hub_id_for_hub_handle(int hubHandle) {
+ if (hubHandle < 0 || hubHandle >= db.hubInfo.numHubs) {
+ return -1;
+ } else {
+ return db.hubInfo.hubs[hubHandle].hub_id;
+ }
+}
+
static int get_hub_id_for_app_instance(int id) {
if (db.appInstances.find(id) == db.appInstances.end()) {
ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
@@ -374,6 +382,9 @@ int handle_os_message(uint32_t msgType, uint32_t hubHandle,
char *msg, int msgLen) {
int retVal;
+ //ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
+ // hubHandle, msgType, msgLen);
+
switch(msgType) {
case CONTEXT_HUB_APPS_ENABLE:
retVal = 0;
@@ -616,7 +627,6 @@ static jobjectArray nativeInitialize(JNIEnv *env, jobject instance)
static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
jbyteArray data_) {
- hub_message_t msg;
jint retVal = -1; // Default to failure
jint *header = env->GetIntArrayElements(header_, 0);
@@ -624,16 +634,30 @@ static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
jbyte *data = env->GetByteArrayElements(data_, 0);
int dataBufferLength = env->GetArrayLength(data_);
+
if (numHeaderElements >= MSG_HEADER_SIZE) {
- if (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0) {
- msg.message_type = header[HEADER_FIELD_MSG_TYPE];
- msg.message_len = dataBufferLength;
- msg.message = data;
- retVal = db.hubInfo.contextHubModule->send_message(
- get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]),
- &msg);
+ bool setAddressSuccess;
+ int hubId;
+ hub_message_t msg;
+
+ if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) {
+ setAddressSuccess = (set_os_app_as_destination(&msg, header[HEADER_FIELD_HUB_HANDLE]) == 0);
+ hubId = get_hub_id_for_hub_handle(header[HEADER_FIELD_HUB_HANDLE]);
+ } else {
+ setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0);
+ hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]);
+ }
+
+ if (setAddressSuccess && hubId >= 0) {
+ msg.message_type = header[HEADER_FIELD_MSG_TYPE];
+ msg.message_len = dataBufferLength;
+ msg.message = data;
+ retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
} else {
- ALOGD("Could not find app instance %d", header[HEADER_FIELD_APP_INSTANCE]);
+ ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
+ header[HEADER_FIELD_APP_INSTANCE],
+ header[HEADER_FIELD_HUB_HANDLE],
+ (int)setAddressSuccess);
}
} else {
ALOGD("Malformed header len");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 30a59934e0a4..9a2e39c752de 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -348,6 +348,8 @@
<protected-broadcast android:name="android.app.action.DEVICE_OWNER_CHANGED" />
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABLE" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNAVAILABLE" />
<!-- Added in N -->
<protected-broadcast android:name="android.intent.action.ANR" />
@@ -399,7 +401,6 @@
<protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
<protected-broadcast android:name="com.android.bluetooth.btservice.action.ALARM_WAKEUP" />
- <protected-broadcast android:name="com.android.ims.IMS_SERVICE_UP" />
<protected-broadcast android:name="com.android.server.action.NETWORK_STATS_POLL" />
<protected-broadcast android:name="com.android.server.action.NETWORK_STATS_UPDATED" />
<protected-broadcast android:name="com.android.server.NetworkTimeUpdateService.action.POLL" />
@@ -459,8 +460,15 @@
<protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
<protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
- <!-- @hide UCE service Notification -->
+ <protected-broadcast android:name="com.android.ims.IMS_SERVICE_UP" />
+ <protected-broadcast android:name="com.android.ims.IMS_INCOMING_CALL" />
<protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_UP" />
+ <protected-broadcast android:name="com.android.intent.action.IMS_FEATURE_CHANGED" />
+ <protected-broadcast android:name="com.android.intent.action.IMS_CONFIG_CHANGED" />
+
+ <protected-broadcast android:name="com.android.internal.location.ALARM_WAKEUP" />
+ <protected-broadcast android:name="com.android.internal.location.ALARM_TIMEOUT" />
+ <protected-broadcast android:name="android.intent.action.GLOBAL_BUTTON" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -2989,6 +2997,11 @@
<permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
android:protectionLevel="signature" />
+ <!-- Required to make calls to {@link android.service.vr.IVrManager}.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_VR_MANAGER"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to whitelist tasks during lock task mode
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
diff --git a/core/res/res/anim/slide_in_enter_micro.xml b/core/res/res/anim/slide_in_enter_micro.xml
index 14a5290a66fe..c70874c626b8 100644
--- a/core/res/res/anim/slide_in_enter_micro.xml
+++ b/core/res/res/anim/slide_in_enter_micro.xml
@@ -19,7 +19,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:zAdjustment="top">
- <translate android:fromYDelta="5%p" android:toXDelta="0"
+ <translate android:fromYDelta="5%p" android:toYDelta="0"
android:duration="417"
android:interpolator="@android:interpolator/launch_task_micro_ydelta" />
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index 30b5a790c1ae..ac37c4a4a8e2 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -17,9 +17,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/actions_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="-16dp"
- android:layout_marginEnd="-16dp">
+ android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/actions"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 0bbaa24a9ad4..992e88e22ad9 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -42,7 +42,7 @@
android:singleLine="true"
/>
<TextView
- android:id="@+id/sub_text_divider"
+ android:id="@+id/header_text_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Material.Notification.Info"
@@ -51,26 +51,7 @@
android:text="@string/notification_header_divider_symbol"
android:visibility="gone"/>
<TextView
- android:id="@+id/header_sub_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
- android:layout_marginStart="2dp"
- android:layout_marginEnd="2dp"
- android:visibility="gone"
- android:singleLine="true"/>
- <TextView
- android:id="@+id/content_info_divider"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
- android:layout_marginStart="2dp"
- android:layout_marginEnd="2dp"
- android:text="@string/notification_header_divider_symbol"
- android:singleLine="true"
- android:visibility="gone"/>
- <TextView
- android:id="@+id/header_content_info"
+ android:id="@+id/header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Material.Notification.Info"
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index d53fb5f2e177..c54fa1895dfa 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -60,9 +60,5 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
- <include
- layout="@layout/notification_material_action_list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
+ <include layout="@layout/notification_material_action_list" />
</LinearLayout>
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index 50aec6bc704a..d87b9d90e48f 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -27,8 +27,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
- android:paddingStart="@dimen/notification_content_margin_start"
- android:paddingEnd="@dimen/notification_content_margin_end"
android:layout_marginTop="@dimen/notification_content_margin_top"
android:clipToPadding="false"
android:orientation="vertical"
@@ -37,6 +35,8 @@
android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
android:orientation="vertical">
<include layout="@layout/notification_template_part_line1"/>
<include layout="@layout/notification_template_progress"/>
@@ -50,14 +50,15 @@
android:layout_weight="1"
android:layout_marginTop="13dp"
android:layout_marginBottom="16dp"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
android:scaleType="centerCrop"
/>
+
<ViewStub android:layout="@layout/notification_material_reply_text"
android:id="@+id/notification_material_reply_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginStart="-16dp"
- android:layout_marginEnd="-16dp"
/>
<include layout="@layout/notification_material_action_list" />
</LinearLayout>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index fdfefe10c3b5..3638b20d864a 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -22,38 +22,45 @@
android:tag="bigText"
>
<include layout="@layout/notification_template_header" />
+
<LinearLayout
- android:id="@+id/notification_main_column"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="top"
- android:paddingStart="@dimen/notification_content_margin_start"
- android:paddingEnd="@dimen/notification_content_margin_end"
- android:layout_marginTop="@dimen/notification_content_margin_top"
- android:clipToPadding="false"
- android:minHeight="@dimen/notification_min_content_height"
- android:orientation="vertical"
- >
- <include layout="@layout/notification_template_part_line1" />
- <include layout="@layout/notification_template_progress" />
- <com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_marginTop="0.5dp"
- android:paddingBottom="@dimen/notification_content_margin_bottom"
- android:textAppearance="@style/TextAppearance.Material.Notification"
- android:singleLine="false"
- android:layout_weight="1"
- android:gravity="top"
- android:visibility="gone"
- />
+ android:layout_height="match_parent"
+ android:layout_gravity="top"
+ android:layout_marginTop="@dimen/notification_content_margin_top"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/notification_main_column"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:paddingStart="@dimen/notification_content_margin_start"
+ android:paddingEnd="@dimen/notification_content_margin_end"
+ android:clipToPadding="false"
+ android:minHeight="@dimen/notification_min_content_height"
+ android:orientation="vertical"
+ >
+ <include layout="@layout/notification_template_part_line1" />
+ <include layout="@layout/notification_template_progress" />
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginTop="0.5dp"
+ android:paddingBottom="@dimen/notification_content_margin_bottom"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:singleLine="false"
+ android:layout_weight="1"
+ android:gravity="top"
+ android:visibility="gone"
+ />
+ </LinearLayout>
+
<ViewStub android:layout="@layout/notification_material_reply_text"
android:id="@+id/notification_material_reply_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="-16dp"
- android:layout_marginEnd="-16dp"
- />
+ android:layout_height="wrap_content" />
<include layout="@layout/notification_material_action_list" />
</LinearLayout>
<include layout="@layout/notification_template_right_icon" />
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 86902db81426..ce9acda14f9f 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -23,87 +23,99 @@
>
<include layout="@layout/notification_template_header" />
<LinearLayout
- android:id="@+id/notification_main_column"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="top"
- android:paddingStart="@dimen/notification_content_margin_start"
- android:paddingEnd="@dimen/notification_content_margin_end"
- android:layout_marginTop="@dimen/notification_content_margin_top"
- android:minHeight="@dimen/notification_min_content_height"
- android:clipToPadding="false"
- android:orientation="vertical"
- >
- <include layout="@layout/notification_template_part_line1"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- <include layout="@layout/notification_template_progress"
- android:layout_width="match_parent"
- android:layout_height="15dp"
- android:layout_marginTop="4dp"/>
- <TextView android:id="@+id/inbox_text0"
- android:textAppearance="@style/TextAppearance.Material.Notification"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text1"
- android:textAppearance="@style/TextAppearance.Material.Notification"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text2"
- android:textAppearance="@style/TextAppearance.Material.Notification"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text3"
- android:textAppearance="@style/TextAppearance.Material.Notification"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text4"
- android:textAppearance="@style/TextAppearance.Material.Notification"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text5"
- android:textAppearance="@style/TextAppearance.Material.Notification"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text6"
- android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_height="match_parent"
+ android:layout_gravity="top"
+ android:layout_marginTop="@dimen/notification_content_margin_top"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/notification_main_column"
android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:paddingStart="@dimen/notification_content_margin_start"
+ android:paddingEnd="@dimen/notification_content_margin_end"
+ android:minHeight="@dimen/notification_min_content_height"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ >
+ <include layout="@layout/notification_template_part_line1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ <include layout="@layout/notification_template_progress"
+ android:layout_width="match_parent"
+ android:layout_height="15dp"
+ android:layout_marginTop="4dp"/>
+ <TextView android:id="@+id/inbox_text0"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text1"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text2"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text3"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text4"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text5"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text6"
+ android:textAppearance="@style/TextAppearance.Material.Notification"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ </LinearLayout>
+ <ViewStub android:layout="@layout/notification_material_reply_text"
+ android:id="@+id/notification_material_reply_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
<include layout="@layout/notification_material_action_list" />
</LinearLayout>
<include layout="@layout/notification_template_right_icon" />
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 4b8640c91f70..fe43e1c5d8b8 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -30,33 +30,37 @@
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
android:elevation="8dp"
- android:background="@color/white" >
- <TextView android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginEnd="8dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:visibility="gone"
- style="?attr/borderlessButtonStyle"
- android:textAppearance="?attr/textAppearanceButton"
- android:textColor="@color/material_deep_teal_500"
- android:gravity="center_vertical"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:singleLine="true"/>
- <TextView android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minHeight="56dp"
- android:textAppearance="?attr/textAppearanceMedium"
- android:gravity="start|center_vertical"
- android:paddingStart="?attr/dialogPreferredPadding"
- android:paddingEnd="?attr/dialogPreferredPadding"
- android:paddingTop="8dp"
- android:layout_below="@id/profile_button"
- android:layout_alignParentLeft="true"
- android:paddingBottom="8dp" />
+ android:background="@color/white">
+
+ <TextView
+ android:id="@+id/profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginEnd="8dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:visibility="gone"
+ style="?attr/borderlessButtonStyle"
+ android:textAppearance="?attr/textAppearanceButton"
+ android:textColor="@color/material_deep_teal_500"
+ android:gravity="center_vertical"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:singleLine="true" />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="56dp"
+ android:textAppearance="?attr/textAppearanceMedium"
+ android:gravity="start|center_vertical"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingEnd="?attr/dialogPreferredPadding"
+ android:paddingTop="8dp"
+ android:layout_below="@id/profile_button"
+ android:layout_alignParentLeft="true"
+ android:paddingBottom="8dp" />
</RelativeLayout>
<ListView
@@ -68,21 +72,23 @@
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
+ android:scrollIndicators="top|bottom"
android:divider="@null" />
- <TextView android:id="@+id/empty"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alwaysShow="true"
- android:text="@string/noApplications"
- android:padding="32dp"
- android:gravity="center"
- android:visibility="gone" />
+ <TextView
+ android:id="@+id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alwaysShow="true"
+ android:text="@string/noApplications"
+ android:padding="32dp"
+ android:gravity="center"
+ android:visibility="gone" />
<LinearLayout
android:id="@+id/button_bar"
android:visibility="gone"
- style="?android:attr/buttonBarStyle"
+ style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_ignoreOffset="true"
@@ -97,26 +103,30 @@
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:elevation="8dp">
- <Button android:id="@+id/button_once"
- android:layout_width="wrap_content"
- android:layout_gravity="start"
- android:maxLines="2"
- style="?android:attr/buttonBarNegativeButtonStyle"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_once"
- android:onClick="onButtonClick" />
- <Button android:id="@+id/button_always"
- android:layout_width="wrap_content"
- android:layout_gravity="end"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_always"
- android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_once"
+ android:layout_width="wrap_content"
+ android:layout_gravity="start"
+ android:maxLines="2"
+ style="?attr/buttonBarNegativeButtonStyle"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_once"
+ android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_always"
+ android:layout_width="wrap_content"
+ android:layout_gravity="end"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ style="?attr/buttonBarPositiveButtonStyle"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_always"
+ android:onClick="onButtonClick" />
</LinearLayout>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 31361e5f9c48..ed7ef5edd817 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -22,8 +22,7 @@
android:layout_height="match_parent"
android:maxWidth="@dimen/resolver_max_width"
android:maxCollapsedHeight="144dp"
- android:id="@id/contentPanel"
- >
+ android:id="@id/contentPanel">
<LinearLayout
android:layout_width="match_parent"
@@ -31,66 +30,75 @@
android:layout_alwaysShow="true"
android:orientation="vertical"
android:background="@color/white"
- android:elevation="8dp" >
+ android:elevation="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="64dp"
- android:orientation="horizontal" >
+ android:orientation="horizontal">
- <ImageView android:id="@+id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="start|top"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- android:layout_marginTop="20dp"
- android:scaleType="fitCenter" />
- <TextView android:id="@+id/title"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:layout_marginStart="16dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="start|center_vertical"
- android:paddingEnd="16dp" />
- <LinearLayout android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginTop="4dp"
- android:layout_marginEnd="4dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:focusable="true"
- android:visibility="gone"
- style="?attr/borderlessButtonStyle">
- <ImageView android:id="@+id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="start|center_vertical"
- android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
- android:layout_marginTop="12dp"
- android:layout_marginBottom="12dp"
- android:scaleType="fitCenter" />
- <TextView android:id="@id/text1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
- android:textAppearance="?attr/textAppearanceButton"
- android:textColor="?attr/textColorPrimary"
- android:minLines="1"
- android:maxLines="1"
- android:ellipsize="marquee" />
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|top"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginTop="20dp"
+ android:scaleType="fitCenter" />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="?attr/listPreferredItemHeight"
+ android:layout_marginStart="16dp"
+ android:textAppearance="?attr/textAppearanceMedium"
+ android:gravity="start|center_vertical"
+ android:paddingEnd="16dp" />
+
+ <LinearLayout
+ android:id="@+id/profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginEnd="4dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp"
+ android:focusable="true"
+ android:visibility="gone"
+ style="?attr/borderlessButtonStyle">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
+ android:scaleType="fitCenter" />
+
+ <TextView
+ android:id="@id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+ android:textAppearance="?attr/textAppearanceButton"
+ android:textColor="?attr/textColorPrimary"
+ android:minLines="1"
+ android:maxLines="1"
+ android:ellipsize="marquee" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/button_bar"
android:visibility="gone"
- style="?android:attr/buttonBarStyle"
+ style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
@@ -104,30 +112,36 @@
android:paddingEnd="12dp"
android:background="@color/white"
android:elevation="8dp">
- <Button android:id="@+id/button_once"
- android:layout_width="wrap_content"
- android:layout_gravity="start"
- android:maxLines="2"
- style="?android:attr/buttonBarNegativeButtonStyle"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_once"
- android:onClick="onButtonClick" />
- <Button android:id="@+id/button_always"
- android:layout_width="wrap_content"
- android:layout_gravity="end"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_always"
- android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_once"
+ android:layout_width="wrap_content"
+ android:layout_gravity="start"
+ android:maxLines="2"
+ style="?attr/buttonBarNegativeButtonStyle"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_once"
+ android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_always"
+ android:layout_width="wrap_content"
+ android:layout_gravity="end"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ style="?attr/buttonBarPositiveButtonStyle"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_always"
+ android:onClick="onButtonClick" />
</LinearLayout>
- <View android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="?android:attr/dividerVertical" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?attr/dividerVertical" />
</LinearLayout>
<ListView
@@ -140,6 +154,6 @@
android:elevation="8dp"
android:nestedScrollingEnabled="true"
android:divider="@null"
- />
+ android:scrollIndicators="top|bottom" />
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 7ca52a3a7a2b..2a16a1ec5d5b 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhoud word versteek volgens beleid"</string>
<string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Skakel oor na persoonlik"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Skakel oor na werk"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakte"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"in te gaan by jou kontakte"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Ligging"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEEL"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"WEIER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Verander sleutelbord"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Ander sleutelborde"</string>
<string name="show_ime" msgid="2506087537466597099">"Hou dit op die skerm terwyl fisieke sleutelbord aktief is"</string>
<string name="hardware" msgid="194658061510127999">"Wys virtuele sleutelbord"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Stel fisieke sleutelbord op"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om taal en uitleg te kies"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidate"</u></string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 200ec3041e88..0668c35f0522 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ይዘቶች በመመሪያ ተደብቀዋል"</string>
<string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ወደ የግል ቀይር"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"ወደ ሥራ ቀይር"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"ዕውቂያዎች"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"የእርስዎ እውቂያዎች ላይ ይድረሱባቸው"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"መገኛ አካባቢ"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"አጋራ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"አትቀበል"</string>
<string name="select_input_method" msgid="8547250819326693584">"ቁልፍ ሰሌዳ ይቀይሩ"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"ሌሎች ቁልፍ ሰሌዳዎች"</string>
<string name="show_ime" msgid="2506087537466597099">"አካላዊ የቁልፍ ሰሌዳ ገቢር ሆኖ ሳለ በማያ ገጽ ላይ አቆየው"</string>
<string name="hardware" msgid="194658061510127999">"ምናባዊ የቁልፍ ሰሌዳን አሳይ"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"አካላዊ ቁልፍ ሰሌዳን ያዋቅሩ"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ቋንቋ እና አቀማመጥን ለመምረጥ መታ ያድርጉ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ዕጩዎች"</u></string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d8127878d447..6a7c76cc545f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -241,10 +241,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"تم إخفاء المحتويات بواسطة السياسة"</string>
<string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"‏نظام Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"التبديل إلى الشخصي"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"التبديل إلى العمل"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"جهات الاتصال"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"الوصول إلى جهات اتصالك"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"الموقع"</string>
@@ -1095,13 +1093,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"مشاركة"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"رفض"</string>
<string name="select_input_method" msgid="8547250819326693584">"تغيير لوحة المفاتيح"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"لوحات المفاتيح الأخرى"</string>
<string name="show_ime" msgid="2506087537466597099">"استمرار عرضها على الشاشة أثناء نشاط لوحة المفاتيح الفعلية"</string>
<string name="hardware" msgid="194658061510127999">"إظهار لوحة المفاتيح الظاهرية"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"تهيئة لوحة المفاتيح الفعلية"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"انقر لاختيار لغة وتنسيق"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"العناصر المرشحة"</u></string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 547995846e9a..e76ce87848d6 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Məzmun siyasət tərəfindən gizlədilib"</string>
<string name="safeMode" msgid="2788228061547930246">"Təhlükəsiz rejim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistemi"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Şəxsi profilə keçirin"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"İş profilinə keçirin"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktlar"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktlarınıza daxil olun"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Yer"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞIN"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RƏDD EDİN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviaturanı dəyişin"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Digər klaviaturalar"</string>
<string name="show_ime" msgid="2506087537466597099">"Fiziki klaviatura aktiv olduğu halda ekranda saxlayın"</string>
<string name="hardware" msgid="194658061510127999">"Virtual klaviaturanı göstərin"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fiziki klaviaturanı konfiqurasiya edin"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dil və tərtibatı seçmək üçün tıklayın"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCÇDEƏFGĞHXIİJKQLMNOÖPRSŞTUÜVYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCÇDEƏFGĞHİIJKLMNOÖPQRSŞTUÜVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"namizədlər"</u></string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9f9b5b8816b0..9231e9a8cc83 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -235,10 +235,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj je sakriven smernicama"</string>
<string name="safeMode" msgid="2788228061547930246">"Bezbedni režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Pređi na Lični profil"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Pređi na profil za Work"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupi kontaktima"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1071,13 +1069,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBIJ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promenite tastaturu"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Druge tastature"</string>
<string name="show_ime" msgid="2506087537466597099">"Zadrži ga na ekranu dok je fizička tastatura aktivna"</string>
<string name="hardware" msgid="194658061510127999">"Prikaži virtuelnu tastaturu"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurišite fizičku tastaturu"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste izabrali jezik i raspored"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index 6848fda5a29f..8a23529da4ef 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Змесціва, схаванае ў адпаведнасці з палітыкай"</string>
<string name="safeMode" msgid="2788228061547930246">"Бяспечны рэжым"</string>
<string name="android_system_label" msgid="6577375335728551336">"Сістэма Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Пераключыцца на асабісты"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Пераключыцца на працоўны"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Кантакты"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"атрымліваць доступ да вашых кантактаў"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Месцазнаходжанне"</string>
@@ -1063,8 +1061,8 @@
<string name="no_permissions" msgid="7283357728219338112">"Дазволу не патрабуецца"</string>
<string name="perm_costs_money" msgid="4902470324142151116">"за гэта можа спаганяцца плата"</string>
<string name="dlg_ok" msgid="7376953167039865701">"ОК"</string>
- <string name="usb_charging_notification_title" msgid="6895185153353640787">"Зарадка гэтай прылады па USB"</string>
- <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Падача сілкавання падключанай прыладзе па USB"</string>
+ <string name="usb_charging_notification_title" msgid="6895185153353640787">"Па USB зараджаецца гэта прыладу"</string>
+ <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Па USB падачецца сілкаванне падключанай прыладзе"</string>
<string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB для перадачы файлаў"</string>
<string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB для перадачы фота"</string>
<string name="usb_midi_notification_title" msgid="4850904915889144654">"USB для MIDI"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"АБАГУЛІЦЬ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"АДХІЛІЦЬ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Змяніць клавіятуру"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Іншыя праграмныя клавіятуры"</string>
<string name="show_ime" msgid="2506087537466597099">"Захоўваць яе на экране ў той час, калі фізічная клавіятура актыўная"</string>
<string name="hardware" msgid="194658061510127999">"Паказаць віртуальную клавіятуру"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Наладжванне фізічнай клавіятуры"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Дакраніцеся, каб выбраць мову і раскладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"кандыдат."</u></string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 4f8f80ce6cfe..76c70024a5a8 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Съдържанието е скрито чрез правило"</string>
<string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Превключване към личния потребителски профил"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Превключване към служебния пoтребителски профил"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"има достъп до контактите ви"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Местоположение"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"СПОДЕЛЯНЕ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОТХВЪРЛЯНЕ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Промяна на клавиатурата"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Други клавиатури"</string>
<string name="show_ime" msgid="2506087537466597099">"Показване на екрана, докато физическата клавиатура е активна"</string>
<string name="hardware" msgid="194658061510127999">"Показване на вирт. клавиатура"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Конфигуриране на физическата клавиатура"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Докоснете, за да изберете език и подредба"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 13284cf33d59..620e532de355 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"নীতির কারণে সামগ্রী লুকানো আছে"</string>
<string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android সিস্টেম"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ব্যক্তিগততে পাল্টান"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"কর্মস্থানে পাল্টান"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"পরিচিতি"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"আপনার পরিচিতিগুলিতে অ্যাক্সেস করুন"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"অবস্থান"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"শেয়ার করুন"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"অস্বীকার করুন"</string>
<string name="select_input_method" msgid="8547250819326693584">"কীবোর্ড পরিবর্তন করুন"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"অন্যান্য কীবোর্ড"</string>
<string name="show_ime" msgid="2506087537466597099">"ফিজিক্যাল কীবোর্ড সক্রিয় থাকার সময় এটিকে স্ক্রীনে রাখুন"</string>
<string name="hardware" msgid="194658061510127999">"ভার্চুয়াল কীবোর্ড দেখান"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ফিজিক্যাল কীবোর্ড কনফিগার করুন"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ভাষা এবং লেআউট নির্বাচন করুন আলতো চাপ দিন"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"প্রার্থীরা"</u></string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index bbc72d581e53..82639af1e131 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -235,10 +235,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj skriven u skladu sa pravilima"</string>
<string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Prebacite se na lični"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Prebacite se na radni"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupa vašim kontaktima"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1071,13 +1069,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PODIJELI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBACI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promijeni tastaturu"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Ostale tastature"</string>
<string name="show_ime" msgid="2506087537466597099">"Prikaži na ekranu dok je fizička tastatura aktivna"</string>
<string name="hardware" msgid="194658061510127999">"Prikaži virtualnu tastaturu"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguriraj fizičku tastaturu"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite za odabir jezika i rasporeda"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 07ba68274eca..6fcadfa26f29 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contingut amagat de conformitat amb la política"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Canvia al perfil personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Canvia al perfil professional"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactes"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedir als contactes"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Ubicació"</string>
@@ -1048,7 +1046,7 @@
<string name="perm_costs_money" msgid="4902470324142151116">"pot ser que comporti càrrecs"</string>
<string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string>
<string name="usb_charging_notification_title" msgid="6895185153353640787">"L\'USB està carregant el dispositiu"</string>
- <string name="usb_supplying_notification_title" msgid="5310642257296510271">"L\'USB subministra energia al dispositiu inserit"</string>
+ <string name="usb_supplying_notification_title" msgid="5310642257296510271">"L\'USB subministra energia al dispositiu connectat"</string>
<string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB per transferir fitxers"</string>
<string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB per transferir fotos"</string>
<string name="usb_midi_notification_title" msgid="4850904915889144654">"USB per a MIDI"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTEIX"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REBUTJA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Canvia el teclat"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Altres teclats"</string>
<string name="show_ime" msgid="2506087537466597099">"El deixa a la pantalla mentre el teclat físic està actiu"</string>
<string name="hardware" msgid="194658061510127999">"Mostra el teclat virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclat físic"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca per seleccionar l\'idioma i el disseny"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0a9aa2be2a8b..127d38bf9e42 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Obsah skrytý zásadami"</string>
<string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Přepnout na osobní profil"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Přepnout na pracovní profil"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakty"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"přístup ke kontaktům"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Poloha"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SDÍLET"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODMÍTNOUT"</string>
<string name="select_input_method" msgid="8547250819326693584">"Změna klávesnice"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Další klávesnice"</string>
<string name="show_ime" msgid="2506087537466597099">"Ponechat na obrazovce, když je aktivní fyzická klávesnice"</string>
<string name="hardware" msgid="194658061510127999">"Zobrazit virtuální klávesnici"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurace fyzické klávesnice"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozvržení"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index dd2d223bfcb5..407f1f8b834e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Indholdet er skjult af politikken"</string>
<string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Skift til Tilpasset"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Skift til arbejde"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktpersoner"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"have adgang til dine kontaktpersoner"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Placering"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEL"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AFVIS"</string>
<string name="select_input_method" msgid="8547250819326693584">"Skift tastatur"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Andre tastaturer"</string>
<string name="show_ime" msgid="2506087537466597099">"Behold den på skærmen, mens det fysiske tastatur er aktivt"</string>
<string name="hardware" msgid="194658061510127999">"Vis virtuelt tastatur"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurer fysisk tastatur"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryk for at vælge sprog og layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b32bea6b8e13..e539a28354dd 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhalte aufgrund der Richtlinien ausgeblendet"</string>
<string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Zu \"Privat\" wechseln"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Zu \"Arbeit\" wechseln"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakte"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"auf Kontakte zuzugreifen"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Standort"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"TEILEN"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ABLEHNEN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatur ändern"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Weitere Tastaturen"</string>
<string name="show_ime" msgid="2506087537466597099">"Auf dem Display einblenden, wenn die physische Tastatur aktiv ist"</string>
<string name="hardware" msgid="194658061510127999">"Virtuelle Tastatur einblenden"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Physische Tastatur konfigurieren"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Zum Auswählen von Sprache und Layout tippen"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"Kandidaten"</u></string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 71351a353c0a..1e891d039231 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Το περιεχόμενο είναι κρυφό βάσει πολιτικής"</string>
<string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
<string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Μετάβαση σε προσωπικό προφίλ"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Μετάβαση σε προφίλ εργασίας"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Επαφές"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"πρόσβαση στις επαφές σας"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Τοποθεσία"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ΚΟΙΝΟΠΟΙΗΣΗ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ΑΠΟΡΡΙΨΗ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Αλλαγή πληκτρολογίου"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Άλλα πληκτρολόγια"</string>
<string name="show_ime" msgid="2506087537466597099">"Να παραμένει στην οθόνη όταν είναι ενεργό το φυσικό πληκτρολόγιο"</string>
<string name="hardware" msgid="194658061510127999">"Εμφάνιση εικονικού πληκτρολ."</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Διαμόρφωση φυσικού πληκτρολογίου"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Πατήστε για να επιλέξετε γλώσσα και διάταξη"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"υποψήφιοι"</u></string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index c222397d00ce..b94222c7efca 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Location"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHARE"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"DECLINE"</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Other keyboards"</string>
<string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
<string name="hardware" msgid="194658061510127999">"Show virtual keyboard"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configure physical keyboard"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c222397d00ce..b94222c7efca 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Location"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHARE"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"DECLINE"</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Other keyboards"</string>
<string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
<string name="hardware" msgid="194658061510127999">"Show virtual keyboard"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configure physical keyboard"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c222397d00ce..b94222c7efca 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Location"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHARE"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"DECLINE"</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Other keyboards"</string>
<string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
<string name="hardware" msgid="194658061510127999">"Show virtual keyboard"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configure physical keyboard"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index afd5f6ccfdea..0bfb9e0b5321 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenido oculto debido a la política"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Cambiar al perfil personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar al perfil de trabajo"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder a los contactos"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Ubicación"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECHAZAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar el teclado"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Otros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Mantener en la pantalla cuando el teclado físico está activo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclado físico"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Presiona para seleccionar el idioma y el diseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 3d5682c63aef..99202abdd5cf 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenidos ocultos por política"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Cambiar a perfil personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar a perfil de trabajo"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder a tus contactos"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Ubicación"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECHAZAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Otros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Debe seguir en pantalla mientras el teclado físico esté activo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclado físico"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar el idioma y el diseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 7b2e108aff43..b1cc97170674 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sisu on eeskirjadega peidetud"</string>
<string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Lülita isiklikule profiilile"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Lülita tööprofiilile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktid"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"juurdepääs kontaktidele"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Asukoht"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"JAGA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"KEELDU"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviatuuri muutmine"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Muud klaviatuurid"</string>
<string name="show_ime" msgid="2506087537466597099">"Hoia seda ekraanil, kui füüsiline klaviatuur on aktiivne"</string>
<string name="hardware" msgid="194658061510127999">"Virtuaalse klaviatuuri kuvam."</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Füüsilise klaviatuuri seadistamine"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Puudutage keele ja paigutuse valimiseks"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidaadid"</u></string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 5bcaed12646f..ea666d975b05 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Gidalerro batzuk ezkutatu dira, gidalerroei jarraiki"</string>
<string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Aldatu profil pertsonalera"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Aldatu laneko profilera"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktuak"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktuak atzitzeko"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Kokapena"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTEKATU"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"BAZTERTU"</string>
<string name="select_input_method" msgid="8547250819326693584">"Aldatu teklatua"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Beste teklatu batzuk"</string>
<string name="show_ime" msgid="2506087537466597099">"Erakutsi pantailan teklatu fisikoa aktibo dagoen bitartean"</string>
<string name="hardware" msgid="194658061510127999">"Erakutsi teklatu birtuala"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguratu teklatu fisikoa"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"hautagaiak"</u></string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 7688af44979e..df9d78fe7a74 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"محتوا بر اساس خط‌مشی پنهان شده است"</string>
<string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"‏سیستم Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"رفتن به نمایه شخصی"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"رفتن به نمایه کاری"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"مخاطبین"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"دسترسی به مخاطبین شما"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"مکان"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"اشتراک‌گذاری"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"نپذیرفتن"</string>
<string name="select_input_method" msgid="8547250819326693584">"تغییر صفحه‌کلید"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"صفحه‌کلیدهای دیگر"</string>
<string name="show_ime" msgid="2506087537466597099">"وقتی صفحه‌کلید فیزیکی فعال است این ویرایشگر را روی صفحه نگه‌می‌دارد"</string>
<string name="hardware" msgid="194658061510127999">"نمایش صفحه‌کلید مجازی"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"پیکربندی صفحه‌کلید فیزیکی"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"برای انتخاب زبان و چیدمان ضربه بزنید"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 9105842a3acd..c86996181e08 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sisältö on piilotettu käytännön perusteella."</string>
<string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Siirry henkilökohtaiseen profiiliin"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Siirry työprofiiliin"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktit"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"käyttää yhteystietoja"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Sijainti"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"JAA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"HYLKÄÄ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Vaihda näppäimistö"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Muut näppäimistöt"</string>
<string name="show_ime" msgid="2506087537466597099">"Pidä näytöllä, kun fyysinen näppäimistö on aktiivinen."</string>
<string name="hardware" msgid="194658061510127999">"Näytä virtuaalinen näppäimistö"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Määritä fyysinen näppäimistö"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Valitse kieli ja asettelu koskettamalla."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidaatit"</u></string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 222501f1fc92..efc8af32e4a1 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenu masqué conformément aux politiques"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
<string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Passer au profil professionnel"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accéder à vos contacts"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Localisation"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTAGER"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUSER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Autres claviers"</string>
<string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
<string name="hardware" msgid="194658061510127999">"Afficher le clavier virtuel"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurer le clavier physique"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Touchez pour sélectionner la langue et la configuration du clavier"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 1b8e03ca556f..4e83fa9619fb 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenu masqué conformément aux règles"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
<string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Passer au profil professionnel"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accéder à vos contacts"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Position"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTAGER"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUSER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Autres claviers"</string>
<string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
<string name="hardware" msgid="194658061510127999">"Afficher le clavier virtuel"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurer le clavier physique"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Appuyer pour sélectionner la langue et la disposition"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index ae5cc617cb13..2fa6087fa6d2 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Ocultouse contido por causa da política"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Cambiar ao perfil persoal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar ao perfil de traballo"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder aos teus contactos"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Localización"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ANULAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manteno na pantalla mentres o teclado físico estea activo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura o teclado físico"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar o idioma e o deseño"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 04876126b575..0b9f4ad8dda9 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"નીતિ દ્વારા સામગ્રી છુપાવાઈ"</string>
<string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android સિસ્ટમ"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"વ્યક્તિગત પર સ્વિચ કરો"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"કાર્ય પર સ્વિચ કરો"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"સંપર્કો"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"તમારા સંપર્કોને ઍક્સેસ કરો"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"સ્થાન"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"શેર કરો"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"નકારો"</string>
<string name="select_input_method" msgid="8547250819326693584">"કીબોર્ડ બદલો"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"અન્ય કીબોર્ડ્સ"</string>
<string name="show_ime" msgid="2506087537466597099">"જ્યારે ભૌતિક કીબોર્ડ સક્રિય હોય ત્યારે તેને સ્ક્રીન પર રાખો"</string>
<string name="hardware" msgid="194658061510127999">"વર્ચ્યુઅલ કીબોર્ડ બતાવો"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ભૌતિક કીબોર્ડ ગોઠવો"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ભાષા અને લેઆઉટ પસંદ કરવા માટે ટૅપ કરો"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ઉમેદવારો"</u></string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f007f89f9fa4..474e81e66670 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"सामग्री पॉलिसी के द्वारा छिपी हुई है"</string>
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफ़ाइल में स्विच करें"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"कार्य प्रोफ़ाइल में स्विच करें"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"संपर्क"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"अपने संपर्कों को ऐक्सेस करें"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"स्थान"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"साझा करें"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"अस्वीकार करें"</string>
<string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदलें"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"अन्य कीबोर्ड"</string>
<string name="show_ime" msgid="2506087537466597099">"भौतिक कीबोर्ड के सक्रिय होने के दौरान इसे स्‍क्रीन पर बनाए रखें"</string>
<string name="hardware" msgid="194658061510127999">"वर्चुअल कीबोर्ड दिखाएं"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"भौतिक कीबोर्ड कॉन्फ़िगर करें"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा और लेआउट चुनने के लिए टैप करें"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"उम्‍मीदवार"</u></string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index af8de3f7ebc4..837aa5662208 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -235,10 +235,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj je skriven prema pravilima"</string>
<string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Prijeđite na osobni"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Prijeđite na radni"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupati vašim kontaktima"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1071,13 +1069,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DIJELI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBIJ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promjena tipkovnice"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Ostale tipkovnice"</string>
<string name="show_ime" msgid="2506087537466597099">"Zadržava se na zaslonu dok je fizička tipkovnica aktivna"</string>
<string name="hardware" msgid="194658061510127999">"Prikaži virtualnu tipkovnicu"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurirajte fizičku tipkovnicu"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste odabrali jezik i raspored"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 6ae5120ddeb0..0c4705da26cf 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"A tartalom irányelv miatt elrejtve"</string>
<string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Átváltás személyes profilra"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Átváltás munkaprofilra"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Névjegyek"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"hozzáférés a névjegyekhez"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Helyadatok"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"MEGOSZTÁS"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ELUTASÍTÁS"</string>
<string name="select_input_method" msgid="8547250819326693584">"Billentyűzet megváltoztatása"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Más billentyűzetek"</string>
<string name="show_ime" msgid="2506087537466597099">"Maradjon a képernyőn, amíg a billentyűzet aktív"</string>
<string name="hardware" msgid="194658061510127999">"Virtuális billentyűzet"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Állítsa be a fizikai billentyűzetet"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Koppintson a nyelv és a billentyűzetkiosztás kiválasztásához"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"jelöltek"</u></string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 1a4a2ebe21c7..4be90da94bb9 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Բովանդակությունը թաքցվել է ըստ քաղաքականության"</string>
<string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Անցնել անհատական պրոֆիլին"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Անցնել աշխատանքային պրոֆիլին"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Կոնտակտներ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"կոնտակտների հասանելիություն"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Տեղադրություն"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ՏՐԱՄԱԴՐԵԼ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ՄԵՐԺԵԼ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Փոխել ստեղնաշարը"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Այլ ստեղնաշարեր"</string>
<string name="show_ime" msgid="2506087537466597099">"Պահել էկրանին մինչդեռ ֆիզիկական ստեղնաշարն ակտիվ է"</string>
<string name="hardware" msgid="194658061510127999">"Ցույց տալ վիրտուալ ստեղնաշարը"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Կազմաձևեք ֆիզիկական ստեղնաշարը"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"թեկնածուները"</u></string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 480a845137f9..72186176a41f 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Konten disembunyikan menurut kebijakan"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Beralih ke Pribadi"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Beralih ke Kantor"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontak"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"mengakses kontak"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokasi"</string>
@@ -1047,8 +1045,8 @@
<string name="no_permissions" msgid="7283357728219338112">"Tidak perlu izin"</string>
<string name="perm_costs_money" msgid="4902470324142151116">"ini mungkin tidak gratis"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Oke"</string>
- <string name="usb_charging_notification_title" msgid="6895185153353640787">"Mengisi daya perangkat ini melalui USB"</string>
- <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Menyuplai daya melalui USB ke perangkat yang terpasang"</string>
+ <string name="usb_charging_notification_title" msgid="6895185153353640787">"Isi daya perangkat ini melalui USB"</string>
+ <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Suplai daya melalui USB ke perangkat yang terpasang"</string>
<string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB untuk transfer file"</string>
<string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB untuk transfer foto"</string>
<string name="usb_midi_notification_title" msgid="4850904915889144654">"USB untuk MIDI"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"BAGIKAN"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TOLAK"</string>
<string name="select_input_method" msgid="8547250819326693584">"Ubah keyboard"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Keyboard lainnya"</string>
<string name="show_ime" msgid="2506087537466597099">"Pertahankan di layar jika keyboard fisik masih aktif"</string>
<string name="hardware" msgid="194658061510127999">"Tampilkan keyboard virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Mengonfigurasi keyboard fisik"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketuk untuk memilih bahasa dan tata letak"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index ce00b0940271..cebc4ccc0235 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Efni falið með reglu"</string>
<string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android kerfið"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Skipta yfir í persónulegt snið"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Skipta yfir í vinnusnið"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Tengiliðir"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"fá aðgang að tengiliðunum þínum"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Staðsetning"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEILA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"HAFNA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Skipta um lyklaborð"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Önnur lyklaborð"</string>
<string name="show_ime" msgid="2506087537466597099">"Haltu því á skjánum meðan vélbúnaðarlyklaborðið er virkt"</string>
<string name="hardware" msgid="194658061510127999">"Sýna sýndarlyklaborð"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Stilla vélbúnaðarlyklaborð"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ýttu til að velja tungumál og útlit"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"möguleikar"</u></string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 19fcf5585b5f..2a73990fad6b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenuti nascosti in base alle norme"</string>
<string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Passa al profilo personale"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Passa al profilo di lavoro"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedere ai contatti"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Posizione"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"CONDIVIDI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RIFIUTO"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambia tastiera"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Altre tastiere"</string>
<string name="show_ime" msgid="2506087537466597099">"Tieni sullo schermo quando è attiva la tastiera fisica"</string>
<string name="hardware" msgid="194658061510127999">"Mostra tastiera virtuale"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura la tastiera fisica"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tocca per selezionare la lingua e il layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidati"</u></string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 41acce9091eb..80435b684b00 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"התוכן מוסתר על ידי המדיניות"</string>
<string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
<string name="android_system_label" msgid="6577375335728551336">"‏מערכת Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"עבור ל\'אישי\'"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"עבור ל\'עבודה\'"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"אנשי קשר"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"גישה אל אנשי הקשר"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"מיקום"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"שתף"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"דחה"</string>
<string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"מקלדות אחרות"</string>
<string name="show_ime" msgid="2506087537466597099">"השאר אותו במסך בזמן שהמקלדת הפיזית פעילה"</string>
<string name="hardware" msgid="194658061510127999">"הצג מקלדת וירטואלית"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"הגדרת מקלדת פיזית"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"מועמדים"</u></string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index dff30b42e054..394775f45bdb 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ポリシーによって非表示になっているコンテンツ"</string>
<string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
<string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"個人用に切り替える"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"仕事用に切り替える"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"連絡先"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"連絡先へのアクセス"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"位置情報"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"共有する"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"共有しない"</string>
<string name="select_input_method" msgid="8547250819326693584">"キーボードの変更"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"その他のキーボード"</string>
<string name="show_ime" msgid="2506087537466597099">"物理キーボードが有効になっている間は、画面に表示されます"</string>
<string name="hardware" msgid="194658061510127999">"仮想キーボードの表示"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"物理キーボードの設定"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"タップして言語とレイアウトを選択してください"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"候補"</u></string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index eaed9dd9b86b..fcc56da78f17 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"შიგთავსი დამალულია წესების შესაბამისად"</string>
<string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"პირად პროფილზე გადართვა"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"სამსახურის პროფილზე გადართვა"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"კონტაქტები"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"თქვენს კონტაქტებზე წვდომა"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"მდებარეობა"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"გაზიარება"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"უარყოფა"</string>
<string name="select_input_method" msgid="8547250819326693584">"კლავიატურის შეცვლა"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"სხვა კლავიატურები"</string>
<string name="show_ime" msgid="2506087537466597099">"აქტიური ფიზიკური კლავიატურისას ეკრანზე შენარჩუნება"</string>
<string name="hardware" msgid="194658061510127999">"ვირტუალური კლავიატურის ჩვენება"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"მოახდინეთ ფიზიკური კლავიატურის კონფიგურაცია"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"შეეხეთ ენისა და განლაგების ასარჩევად"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"კანდიდატები"</u></string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index aecf49f8d969..6eaa770f9cb9 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Мазмұн саясатқа сай жасырылған"</string>
<string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android жүйесі"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Жекеге ауысу"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Жұмысқа ауысу"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контактілер"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"контактілерге кіру"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Орын"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"БӨЛІСУ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ҚАБЫЛДАМАУ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Пернетақтаны өзгерту"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Басқа пернетақталар"</string>
<string name="show_ime" msgid="2506087537466597099">"Физикалық пернетақта белсенді кезде оны экранда ұстау"</string>
<string name="hardware" msgid="194658061510127999">"Виртуалды пернетақтаны көрсету"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Физикалық пернетақтаны конфигурациялау"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тіл мен пернетақта схемасын таңдау үшін түртіңіз"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"үміткерлер"</u></string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index fb80d6e603e7..30d3c0a4a0a4 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"មាតិកាត្រូវបានលាក់ដោយផ្អែកលើគោលការណ៍"</string>
<string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
<string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ​​ Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ប្តូរទៅផ្ទាល់ខ្លួន"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"ប្តូរទៅការងារ"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"ទំនាក់ទំនង"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ចូលប្រើទំនាក់ទំនងរបស់អ្នក"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ទីតាំង"</string>
@@ -1065,13 +1063,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ចែករំលែក"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"បដិសេធ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ប្ដូរ​ក្ដារចុច"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"ក្តារចុចផ្សេងទៀត"</string>
<string name="show_ime" msgid="2506087537466597099">"ទុកវានៅលើអេក្រង់ខណៈពេលក្តារចុចពិតប្រាកដកំពុងសកម្ម"</string>
<string name="hardware" msgid="194658061510127999">"បង្ហាញក្ដារចុចនិម្មិត"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"កំណត់រចនាសម្ព័ន្ធក្តារចុចពិតប្រាកដ"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ប៉ះដើម្បីជ្រើសភាសា និងប្លង់"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"បេក្ខជន"</u></string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index f2e5024dbe7f..087b399ed54e 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ನೀತಿಯಿಂದ ಮರೆಮಾಡಲಾಗಿರುವ ವಿಷಯಗಳು"</string>
<string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android ಸಿಸ್ಟಂ"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ವೈಯಕ್ತಿಕಗೆ ಬದಲಿಸಿ"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"ಕೆಲಸಕ್ಕೆ ಬದಲಿಸು"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"ಸಂಪರ್ಕಗಳು"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ಸ್ಥಳ"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ನಿರಾಕರಿಸು"</string>
<string name="select_input_method" msgid="8547250819326693584">"ಕೀಬೋರ್ಡ್ ಬದಲಿಸಿ"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"ಇತರೆ ಕೀಬೋರ್ಡ್‌ಗಳು"</string>
<string name="show_ime" msgid="2506087537466597099">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅದನ್ನು ಪರದೆಯ ಮೇಲೆ ಇರಿಸಿಕೊಳ್ಳಿ"</string>
<string name="hardware" msgid="194658061510127999">"ವರ್ಚ್ಯುಯಲ್ ಕೀಬೋರ್ಡ್ ತೋರಿಸು"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಕಾನ್ಫಿಗರ್ ಮಾಡಿ"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ಅಭ್ಯರ್ಥಿಗಳು"</u></string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index dc69ee99146e..52de5bab91c7 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"콘텐츠가 정책에 의해 숨겨졌습니다."</string>
<string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"개인으로 전환"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"직장으로 전환"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"주소록"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"주소록에 접근할 수 있도록"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"위치"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"공유"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"거부"</string>
<string name="select_input_method" msgid="8547250819326693584">"키보드 변경"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"기타 키보드"</string>
<string name="show_ime" msgid="2506087537466597099">"물리적 키보드가 활성 상태인 경우 화면에 켜 둠"</string>
<string name="hardware" msgid="194658061510127999">"가상 키보드 표시"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"물리적 키보드 설정"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"탭하여 언어와 레이아웃을 선택하세요."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"가능한 원인"</u></string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 03951a444c46..34cc7e50a5d7 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Тийиштүү саясат боюнча жашырылган мазмундар"</string>
<string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android Тутуму"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Жеке профилге которулуу"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Жумуш профилине которулуу"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Байланыштар"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"байланыштарыңызга уруксат"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Жайгашкан жер"</string>
@@ -1064,13 +1062,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"БӨЛҮШҮҮ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ЧЕТКЕ КАГУУ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Баскычтопту өзгөртүү"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Башка баскычтоптор"</string>
<string name="show_ime" msgid="2506087537466597099">"Баскычтоп иштетилгенде экранда көрүнүп турсун"</string>
<string name="hardware" msgid="194658061510127999">"Виртуалдык баскычтоп"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Аппараттык баскычтопту конфигурациялоо"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тил жана калып тандоо үчүн таптап коюңуз"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"талапкерлер"</u></string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index f64f8df12eaf..ea62f9b93a54 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ເນື້ອຫາຖືກເຊື່ອງຕາມນະໂຍບາຍ"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ສະລັບໄປໂປຣໄຟລ໌ສ່ວນຕົວ"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"ສະລັບໄປໂປຣໄຟລ໌ວຽ."</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"ລາຍຊື່"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ເຂົ້າ​ຫາ​ລາຍ​ຊື່​ຂອງ​ທ່ານ"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ສະ​ຖານ​ທີ່"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ແບ່ງປັນ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ປະຕິເສດ"</string>
<string name="select_input_method" msgid="8547250819326693584">"​ປ່ຽນ​ແປ້ນ​ພິມ"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"ແປ້ນພິມອື່ນໆ"</string>
<string name="show_ime" msgid="2506087537466597099">"ເປີດໃຊ້ໃຫ້ມັນຢູ່ໃນໜ້າຈໍໃນຂະນະທີ່ໃຊ້ແປ້ນພິມພາຍນອກຢູ່"</string>
<string name="hardware" msgid="194658061510127999">"ສະແດງແປ້ນພິມສະເໝືອນ"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ຕັ້ງຄ່າແປ້ນພິມພາຍນອກ"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ແຕະເພື່ອເລືອກພາສາ ແລະ ໂຄງແປ້ນພິມ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ຕົວເລືອກ"</u></string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 517a069a4aee..3e815ecee396 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Turinys paslėptas vadovaujantis politika"</string>
<string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
<string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Perjungti į asmeninį režimą"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Perjungti į darbo režimą"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktai"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pasiekti kontaktus"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Vietovė"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"BENDRINTI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ATMESTI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviatūros keitimas"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Kitos klaviatūros"</string>
<string name="show_ime" msgid="2506087537466597099">"Palikti ekrane, kol fizinė klaviatūra aktyvi"</string>
<string name="hardware" msgid="194658061510127999">"Rodyti virtualiąją klaviatūrą"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fizinės klaviatūros konfigūravimas"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Palieskite, kad pasirinktumėte kalbą ir išdėstymą"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidatai"</u></string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 8d8f99b6d66c..56001fc07de1 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -235,10 +235,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Saskaņā ar politiku saturs ir paslēpts."</string>
<string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Pārslēgt personīgo profilu"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Pārslēgt darba profilu"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktpersonas"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"piekļūt jūsu kontaktpersonu datiem"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Atrašanās vieta"</string>
@@ -1071,13 +1069,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"KOPĪGOT"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"NORAIDĪT"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatūras maiņa"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Citas tastatūras"</string>
<string name="show_ime" msgid="2506087537466597099">"Paturēt ekrānā, kamēr ir aktīva fiziskā tastatūra"</string>
<string name="hardware" msgid="194658061510127999">"Virtuālās tastatūras rādīšana"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fiziskās tastatūras konfigurēšana"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Pieskarieties, lai atlasītu valodu un izkārtojumu"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidāti"</u></string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 71c19517b8d1..060a9fa9fc33 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содржините се скриени поради политиката"</string>
<string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Систем Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Префрлете на личен профил"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Префрли на работен профил"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"пристапува до контактите"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Локација"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"СПОДЕЛИ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОДБИЈ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Измени тастатура"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Други тастатури"</string>
<string name="show_ime" msgid="2506087537466597099">"Прикажувај го на екранот додека е активна физичката тастатура"</string>
<string name="hardware" msgid="194658061510127999">"Прикажи виртуелна тастатура"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Конфигурирајте физичка тастатура"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Допрете за избирање јазик и распоред"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 92f9282cd068..f6ff1d8b5ffd 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"നയം അനുസരിച്ച് ഉള്ളടക്കം മറച്ചിരിക്കുന്നു"</string>
<string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android സിസ്റ്റം"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"വ്യക്തിഗത പ്രൊഫൈലിലേക്ക് മാറുക"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"കോൺടാക്റ്റുകൾ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്‌സസ്സ് ചെയ്യുക"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ലൊക്കേഷൻ"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"പങ്കിടുക"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"നിരസിക്കുക"</string>
<string name="select_input_method" msgid="8547250819326693584">"കീബോഡ് മാറ്റുക"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"മറ്റ് കീബോർഡുകൾ"</string>
<string name="show_ime" msgid="2506087537466597099">"ഫിസിക്കൽ കീബോർഡ് സജീവമായിരിക്കുമ്പോൾ സ്ക്രീനിൽ നിലനിർത്തുക"</string>
<string name="hardware" msgid="194658061510127999">"വെർച്വൽ കീബോർഡ് കാണിക്കുക"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ഫിസിക്കൽ കീബോർഡ് കോൺഫിഗർ ചെയ്യുക"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ഭാഷയും ലേഔട്ടും തിരഞ്ഞെടുക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"കാൻഡിഡേറ്റുകൾ"</u></string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index c1cba4feacf4..75105e6a9252 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Удирдамжийн дагуу нуусан агуулга"</string>
<string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"\"Хувийн\" руу шилжих"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"\"Ажлын\" руу шилжих"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Харилцагчдын хаяг"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"харилцагч руугаа хандах"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Байршил"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ХУВААЛЦАХ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ТАТГАЛЗАХ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Гарыг өөрчлөх"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Бусад гар"</string>
<string name="show_ime" msgid="2506087537466597099">"Бодит гар идэвхтэй үед үүнийг дэлгэцэнд харуулна уу"</string>
<string name="hardware" msgid="194658061510127999">"Хийсвэр гарыг харуулах"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Биет гарыг хэлбэрт оруулах"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"нэр дэвшигч"</u></string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index f41e6ed5d2c3..8a3e56469e83 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"धोरणाद्वारे सामग्री लपविली"</string>
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"वैयक्तिकवर स्विच करा"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"कार्यावर स्विच करा"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"संपर्क"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"आपल्या संपर्कांवर प्रवेश"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"स्थान"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"सामायिक करा"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"नकार द्या"</string>
<string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदला"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"इतर कीबोर्ड"</string>
<string name="show_ime" msgid="2506087537466597099">"भौतिक कीबोर्ड सक्रिय असताना त्यास स्क्रीनवर ठेवा"</string>
<string name="hardware" msgid="194658061510127999">"व्हर्च्युअल कीबोर्ड दर्शवा"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"वास्तविक कीबोर्ड कॉन्फिगर करा"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"उमेदवार"</u></string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 9a69bf97af91..5db9c779ef34 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Kandungan disembunyikan oleh dasar"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Beralih kepada Peribadi"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Beralih kepada Kerja"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kenalan"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"mengakses kenalan anda"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokasi"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"KONGSI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TOLAK"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tukar papan kekunci"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Papan kekunci lain"</string>
<string name="show_ime" msgid="2506087537466597099">"Pastikannya pada skrin, semasa papan kekunci fizikal aktif"</string>
<string name="hardware" msgid="194658061510127999">"Tunjukkan papan kekunci maya"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurasikan papan kekunci fizikal"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketik untuk memilih bahasa dan susun atur"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index b3c80d59f33b..5e5ec4e03953 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"မူဝါဒမှ အကြောင်းအရာများကို ဝှက်ထားသည်"</string>
<string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android စနစ်"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ကိုယ်ပိုင်သီးသန့်အဖြစ် ပြောင်းပါ"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"အလုပ်သို့ ပြောင်းပါ"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"အဆက်အသွယ်များ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"သင့် အဆက်အသွယ်များအား ဝင်ရောက်သုံးရန်"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"တည်နေရာ"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"မျှဝေပါ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ငြင်းပယ်ပါ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ကီးဘုတ် ပြောင်းလဲရန်"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"အခြားကီးဘုတ်များ"</string>
<string name="show_ime" msgid="2506087537466597099">"စက်၏ကီးဘုတ်ကိုအသုံးပြုနေစဉ် ၎င်းကိုမျက်နှာပြင်ပေါ်တွင် ထားပါ"</string>
<string name="hardware" msgid="194658061510127999">"ကီးဘုတ်အတုပြရန်"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ရုပ်ပိုင်းဆိုင်ရာ အသွင်အပြင်ကို ပြင်ဆင်သတ်မှတ်ပါ"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ဘာသာစကားနှင့် အသွင်အပြင်ရွေးချယ်ရန် တို့ပါ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ရွေးချယ်ခံမည့်သူ"</u></string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index bebf59337422..cfccdeb33d87 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Innholdet er skjult i henhold til retningslinjene"</string>
<string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Bytt til den personlige profilen"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Bytt til jobbprofilen"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakter"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"se kontaktene dine"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Posisjon"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEL"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AVSLÅ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Endre tastatur"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Andre tastaturoppsett"</string>
<string name="show_ime" msgid="2506087537466597099">"Ha den på skjermen mens det fysiske tastaturet er aktivt"</string>
<string name="hardware" msgid="194658061510127999">"Vis det virtuelle tastaturet"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurer et fysisk tastatur"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trykk for å velge språk og layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
<string name="candidates_style" msgid="4333913089637062257">"TAG_FONT"<u>"kandidater"</u>"CLOSE_FONT"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 24bb1f0435db..fb817b593423 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"नीतिद्वारा लुकाइएका सामग्री"</string>
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"एन्ड्रोइड प्रणाली"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफाइलमा स्विच गर्नुहोस्"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"कार्य प्रोफाइलमा स्विच गर्नुहोस्"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"सम्पर्कहरू"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"तपाईँको सम्पर्कमा पहुँच गर्नुहोस्"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"स्थान"</string>
@@ -1069,13 +1067,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"साझेदारी गर्नुहोस्"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"अस्वीकार गर्नुहोस्"</string>
<string name="select_input_method" msgid="8547250819326693584">"कुञ्जीपाटी परिवर्तन गर्नुहोस्"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"अन्य किबोर्डहरू"</string>
<string name="show_ime" msgid="2506087537466597099">"भौतिक किबोर्ड सक्रिय हुँदा यसलाई स्क्रिनमा राख्नुहोस्"</string>
<string name="hardware" msgid="194658061510127999">"भर्चुअल किबोर्ड देखाउनुहोस्"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"फिजिकल किबोर्डलाई कन्फिगर गर्नुहोस्"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"उम्मेदवार"</u></string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5759cad68922..3de8496872af 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Content verborgen op basis van beleid"</string>
<string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Overschakelen naar persoonlijk profiel"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Overschakelen naar werkprofiel"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacten"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"toegang krijgen tot je contacten"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Locatie"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELEN"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"WEIGEREN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Toetsenbord wijzigen"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Andere toetsenborden"</string>
<string name="show_ime" msgid="2506087537466597099">"Dit op het scherm weergeven terwijl het fysieke toetsenbord actief is"</string>
<string name="hardware" msgid="194658061510127999">"Virtueel toetsenbord tonen"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fysiek toetsenbord configureren"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om een taal en indeling te selecteren"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidaten"</u></string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index b984760d2a04..87f973fe5b40 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ਨੀਤੀ ਦੁਆਰਾ ਸਮੱਗਰੀ ਲੁਕਾਈ ਗਈ"</string>
<string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ਨਿੱਜੀ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"ਕੰਮ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"ਸੰਪਰਕ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਨੂੰ ਐਕਸੈਸ ਕਰੋ"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ਸਾਂਝੀ ਕਰੋ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ਕੀਬੋਰਡ ਬਦਲੋ"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"ਹੋਰ ਕੀ-ਬੋਰਡ"</string>
<string name="show_ime" msgid="2506087537466597099">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਸਰਗਰਮ ਹੋਣ ਦੌਰਾਨ ਇਸ ਨੂੰ ਸਕ੍ਰੀਨ \'ਤੇ ਬਣਾਈ ਰੱਖੋ"</string>
<string name="hardware" msgid="194658061510127999">"ਵਰਚੁਅਲ ਕੀ-ਬੋਰਡ ਵਿਖਾਓ"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਦਾ ਸੰਰੂਪਣ ਕਰੋ"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ਭਾਸ਼ਾ ਅਤੇ ਖਾਕਾ ਚੁਣਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ਉਮੀਦਵਾਰ"</u></string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7248f4a8623e..6be9a9d70878 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Treść ukryta z powodu zasad"</string>
<string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
<string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Włącz profil osobisty"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Włącz profil do pracy"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakty"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"dostęp do kontaktów"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokalizacja"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"UDOSTĘPNIJ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODRZUĆ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmień klawiaturę"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Inne klawiatury"</string>
<string name="show_ime" msgid="2506087537466597099">"Pozostaw na ekranie, gdy aktywna jest klawiatura fizyczna"</string>
<string name="hardware" msgid="194658061510127999">"Pokaż klawiaturę wirtualną"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Skonfiguruj klawiaturę fizyczną"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Kliknij, by wybrać język i układ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandydaci"</u></string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index bddb0fcac60e..c8004bf7606d 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Alternar para \"Trabalho\""</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acesse seus contatos"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Local"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurar teclado físico"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 68c4bd93e12d..c2ba8ad701b5 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Mudar para pessoal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Mudar para trabalho"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"aceder aos contactos"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Localização"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTILHAR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manter no ecrã enquanto o teclado físico estiver ativo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar o teclado virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurar teclado físico"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o esquema"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index bddb0fcac60e..c8004bf7606d 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Alternar para \"Trabalho\""</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acesse seus contatos"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Local"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurar teclado físico"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 58c93834c898..7485e65361a1 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -235,10 +235,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conținutul este ascuns conform politicii"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Comutați la Personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Comutați la Serviciu"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Persoane de contact"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceseze persoanele de contact"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Locație"</string>
@@ -1071,13 +1069,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"TRIMITEȚI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUZAȚI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Schimbați tastatura"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Alte tastaturi"</string>
<string name="show_ime" msgid="2506087537466597099">"Se păstrează pe ecran cât timp este activată tastatura fizică"</string>
<string name="hardware" msgid="194658061510127999">"Afișați tastatura virtuală"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurați tastatura fizică"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Atingeți pentru a selecta limba și aspectul"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidați"</u></string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 345bb49cb076..5926bfdf1b2c 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содержимое скрыто в соответствии с заданными правилами"</string>
<string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Перейти в личный профиль"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Перейти в рабочий профиль"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакты"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"доступ к контактам"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Местоположение"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ПРЕДОСТАВИТЬ ДОСТУП"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОТКЛОНИТЬ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Выбор раскладки"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Другие клавиатуры"</string>
<string name="show_ime" msgid="2506087537466597099">"Показывать на экране, когда физическая клавиатура включена"</string>
<string name="hardware" msgid="194658061510127999">"Виртуальная клавиатура"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Настройка физической клавиатуры"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Нажмите, чтобы выбрать язык и раскладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"варианты"</u></string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index f01ab61dfe98..6c76da0e7981 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ප්‍රතිපත්තිය විසින් අන්තර්ගතය සඟවන ලදී"</string>
<string name="safeMode" msgid="2788228061547930246">"ආරක්‍ෂිත ආකාරය"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android පද්ධතිය"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"පුද්ගලික වෙත මාරු වන්න"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"කාර්යාලය වෙත මාරු වන්න"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"සම්බන්ධතා"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ඔබේ සම්බන්ධතාවලට පිවිසෙන්න"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ස්ථානය"</string>
@@ -1065,13 +1063,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"බෙදා ගන්න"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ප්‍රතික්ෂේප කරන්න"</string>
<string name="select_input_method" msgid="8547250819326693584">"යතුරු පුවරු වෙනස් කිරීම"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"වෙනත් යතුරු පුවරු"</string>
<string name="show_ime" msgid="2506087537466597099">"භෞතික යතුරු පුවරුව සක්‍රිය අතරතුර එය තිරය මත තබා ගන්න"</string>
<string name="hardware" msgid="194658061510127999">"අතථ්‍ය යතුරු පුවරුව පෙන්වන්න"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"භෞතික යතුරු පුවරුව වින්‍යාස කරන්න"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"භාෂාව හා පිරිසැලසුම තේරීමට තට්ටු කරන්න"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"අපේක්ෂකයන්"</u></string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 1a3ef4cefbaf..ec45070f83e0 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Obsah je na základe pravidiel skrytý"</string>
<string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Prepnúť na osobný"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Prepnúť na pracovný"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakty"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"prístup k vašim kontaktom"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Poloha"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ZDIEĽAŤ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODMIETNUŤ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmeniť klávesnicu"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Ďalšie klávesnice"</string>
<string name="show_ime" msgid="2506087537466597099">"Ponechať na obrazovke, keď je aktívna fyzická klávesnica"</string>
<string name="hardware" msgid="194658061510127999">"Zobraziť virtuálnu klávesnicu"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurácia fyzickej klávesnice"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozloženie"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c102abbb1c48..b2dba7e0a686 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Pravilnik je skril vsebino"</string>
<string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Preklop na osebni profil"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Preklop na delovni profil"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Stiki"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"dostop do stikov"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SKUPNA RABA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"NE SPREJMEM"</string>
<string name="select_input_method" msgid="8547250819326693584">"Sprememba tipkovnice"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Druge tipkovnice"</string>
<string name="show_ime" msgid="2506087537466597099">"Ohrani na zaslonu, dokler je aktivna fizična tipkovnica"</string>
<string name="hardware" msgid="194658061510127999">"Pokaži navidezno tipkovnico"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguriranje fizične tipkovnice"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dotaknite se, če želite izbrati jezik in postavitev."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 9151893c6064..1846399b5a2d 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Përmbajtja është e fshehur për shkak të politikës"</string>
<string name="safeMode" msgid="2788228061547930246">"Modaliteti i sigurisë"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemi \"android\""</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Ndryshoje te \"Personale\""</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Ndryshoje te \"Puna\""</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktet"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"qasu te kontaktet e tua"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Vendndodhja"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHPËRNDA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUZO"</string>
<string name="select_input_method" msgid="8547250819326693584">"Ndërro tastierë"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Tastierat e tjera"</string>
<string name="show_ime" msgid="2506087537466597099">"Mbaje në ekran ndërsa tastiera fizike është aktive"</string>
<string name="hardware" msgid="194658061510127999">"Shfaq tastierën virtuale"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguro tastierën fizike"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trokit për të zgjedhur gjuhën dhe strukturën"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidatë"</u></string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 9f8c2c0e5509..2112dbb5afe6 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -235,10 +235,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Садржај је сакривен смерницама"</string>
<string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Пређи на Лични профил"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Пређи на профил за Work"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"приступи контактима"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Локација"</string>
@@ -1071,13 +1069,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ДЕЛИ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОДБИЈ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Промените тастатуру"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Друге тастатуре"</string>
<string name="show_ime" msgid="2506087537466597099">"Задржи га на екрану док је физичка тастатура активна"</string>
<string name="hardware" msgid="194658061510127999">"Прикажи виртуелну тастатуру"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Конфигуришите физичку тастатуру"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Додирните да бисте изабрали језик и распоред"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d3855f8d0952..832d4a2bf213 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Innehåll har dolts p.g.a. en policy"</string>
<string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Byt till din personliga profil"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Byt till jobbprofilen"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakter"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"få tillgång till dina kontakter"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Plats"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AVVISA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Byt tangentbord"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Andra tangentbord"</string>
<string name="show_ime" msgid="2506087537466597099">"Ha kvar den på skärmen när det fysiska tangentbordet används"</string>
<string name="hardware" msgid="194658061510127999">"Visa virtuellt tangentbord"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurera fysiskt tangentbord"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryck om du vill välja språk och layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index fd5c2c73f261..e0a32f6a61bb 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -235,10 +235,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Maudhui yamefichwa kulingana na sera"</string>
<string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
<string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Badili uweke wasifu wa Binafsi"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Badili uweke wasifu wa Kazini"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Anwani"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ifikie anwani zako"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Mahali"</string>
@@ -1065,13 +1063,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHIRIKI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"KATAA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Badilisha kibodi"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Kibodi zingine"</string>
<string name="show_ime" msgid="2506087537466597099">"Iweke kwenye skrini wakati kibodi inapotumika"</string>
<string name="hardware" msgid="194658061510127999">"Onyesha kibodi pepe"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Sanidi kibodi halisi"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Gonga ili uchague lugha na muundo"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"wagombeaji"</u></string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index f92177a06406..773301f2cad5 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"கொள்கையின்படி உள்ளடக்கம் மறைக்கப்பட்டது"</string>
<string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android அமைப்பு"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"தனிப்பட்ட சுயவிவரத்திற்கு மாறு"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"பணிச் சுயவிவரத்திற்கு மாறு"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"தொடர்புகள்"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"தொடர்புகளை அணுகும்"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"இருப்பிடம்"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"பகிர்"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"வேண்டாம்"</string>
<string name="select_input_method" msgid="8547250819326693584">"விசைப்பலகையை மாற்று"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"பிற விசைப்பலகைகள்"</string>
<string name="show_ime" msgid="2506087537466597099">"கைமுறை விசைப்பலகை இயக்கத்தில் இருக்கும் போது IMEஐ திரையில் வைத்திரு"</string>
<string name="hardware" msgid="194658061510127999">"விர்ச்சுவல் விசைப்பலகையை காட்டு"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"கைமுறை விசைப்பலகையை உள்ளமைக்கவும்"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"மொழியையும் தளவமைப்பையும் தேர்ந்தெடுக்க, தட்டவும்"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"கேன்டிடேட்ஸ்"</u></string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 9b5fc0188625..4809c989db2d 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"విధానం ద్వారా కంటెంట్‌లు దాచబడ్డాయి"</string>
<string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android సిస్టమ్"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"వ్యక్తిగతానికి మార్చు"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"కార్యాలయానికి మార్చు"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"పరిచయాలు"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"మీ పరిచయాలను ప్రాప్యత చేయడానికి"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"స్థానం"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"భాగస్వామ్యం చేయి"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"తిరస్కరిస్తున్నాను"</string>
<string name="select_input_method" msgid="8547250819326693584">"కీబోర్డ్‌ను మార్చు"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"ఇతర కీబోర్డ్‌లు"</string>
<string name="show_ime" msgid="2506087537466597099">"దీన్ని భౌతిక కీబోర్డ్ సక్రియంగా ఉన్నప్పుడు స్క్రీన్‌పై ఉంచుతుంది"</string>
<string name="hardware" msgid="194658061510127999">"వర్చువల్ కీబోర్డ్‌ను చూపు"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"భౌతిక కీబోర్డుని కాన్ఫిగర్ చేయండి"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"భాష మరియు లేఅవుట్‌ను ఎంచుకోవడానికి నొక్కండి"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"క్యాండిడేట్‌లు"</u></string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ca401bc93206..0ea2e520bc6c 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"มีการซ่อนเนื้อหาโดยนโยบาย"</string>
<string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
<string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"เปลี่ยนไปใช้โปรไฟล์ส่วนตัว"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"เปลี่ยนไปใช้โปรไฟล์งาน"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"รายชื่อติดต่อ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"เข้าถึงรายชื่อติดต่อ"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ตำแหน่ง"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"แชร์"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ปฏิเสธ"</string>
<string name="select_input_method" msgid="8547250819326693584">"เปลี่ยนแป้นพิมพ์"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"แป้นพิมพ์อื่นๆ"</string>
<string name="show_ime" msgid="2506087537466597099">"เปิดทิ้งไว้บนหน้าจอในระหว่างใช้งานแป้นพิมพ์จริง"</string>
<string name="hardware" msgid="194658061510127999">"แสดงแป้นพิมพ์เสมือน"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"กำหนดค่าแป้นพิมพ์จริง"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"แตะเพื่อเลือกภาษาและรูปแบบ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ตัวเลือก"</u></string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 1a63a99a5294..00918a4fb9fc 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Itinago ang mga content alinsunod sa patakaran"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Lumipat sa Personal"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Lumipat sa para sa Trabaho"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Mga Contact"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ina-access ang iyong mga contact"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokasyon"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"IBAHAGI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TANGGIHAN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Baguhin ang keyboard"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Iba pang mga keyboard"</string>
<string name="show_ime" msgid="2506087537466597099">"Panatilihin ito sa screen habang aktibo ang pisikal na keyboard"</string>
<string name="hardware" msgid="194658061510127999">"Ipakita ang virtual keyboard"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"I-configure ang pisikal na keyboard"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"I-tap upang pumili ng wika at layout"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"mga kandidato"</u></string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e4a44d20f57d..4db8264743ff 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"İçerikler politika nedeniyle gizlendi"</string>
<string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Kişisel Profile Geç"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"İş Profiline Geç"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kişiler"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"kişilerinize erişme"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Konum"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REDDET"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klavyeyi değiştir"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Diğer klavyeler"</string>
<string name="show_ime" msgid="2506087537466597099">"Fiziksel klavye etkin durumdayken ekranda tut"</string>
<string name="hardware" msgid="194658061510127999">"Sanal klavyeyi göster"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fiziksel klavyeyi yapılandırın"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dili ve düzeni seçmek için hafifçe dokunun"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"adaylar"</u></string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index a6020e8a47bf..fe7be12de34e 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -237,10 +237,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Вміст сховано згідно з правилом"</string>
<string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Перейти в особистий профіль"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Перейти в робочий профіль"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"отримувати доступ до контактів"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Геодані"</string>
@@ -1079,13 +1077,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ПОДІЛИТИСЯ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ВІДХИЛИТИ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Змінити клавіатуру"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Інші клавіатури"</string>
<string name="show_ime" msgid="2506087537466597099">"Утримуйте на екрані, коли активна фізична клавіатура"</string>
<string name="hardware" msgid="194658061510127999">"Показати віртуальну клавіатуру"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Налаштуйте фізичну клавіатуру"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Торкніться, щоб вибрати мову та розкладку"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index b515c55f2be9..5236b7fae62b 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"مواد پالیسی کے تحت مخفی ہے"</string>
<string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string>
<string name="android_system_label" msgid="6577375335728551336">"‏Android سسٹم"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"ذاتی پر سوئچ کریں"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"کام پر سوئچ کریں"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"رابطے"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"اپنے رابطوں تک رسائی حاصل کریں"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"مقام"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"اشتراک کریں"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"مسترد کریں"</string>
<string name="select_input_method" msgid="8547250819326693584">"کی بورڈ تبدیل کریں"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"دیگر کی بورڈز"</string>
<string name="show_ime" msgid="2506087537466597099">"‏جب فزیکل کی بورڈ فعال ہو تو IME کو اسکرین پر رکھیں"</string>
<string name="hardware" msgid="194658061510127999">"ورچوئل کی بورڈ دکھائیں"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"فزیکل کی بورڈ کنفیگر کریں"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"زبان اور لے آؤٹ منتخب کرنے کیلئے تھپتھپائیں"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"امیدواران"</u></string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 6323f52dc3f2..6cb65a316a7e 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Qoidaga muvofiq kontent yashirilgan"</string>
<string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android tizimi"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Shaxsiy profilga o‘tish"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Ishchi profilga o‘tish"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktlar"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktlarga kirish"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Joylashuv"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ULASHISH"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RAD ETISH"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviaturani o‘zgartirish"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Boshqa klaviaturalar"</string>
<string name="show_ime" msgid="2506087537466597099">"Tashqi klaviaturadan foydalanilayotganda buni ekranda saqlab turish"</string>
<string name="hardware" msgid="194658061510127999">"Virtual klaviatura ko‘rsatilsin"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Tashqi klaviaturani sozlash"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Til va sxemani belgilash uchun bosing"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"nomzodlar"</u></string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 10516afd2d72..29eef922e02f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Nội dung bị ẩn theo chính sách"</string>
<string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
<string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Chuyển sang Cá nhân"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Chuyển sang Công việc"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Danh bạ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"truy cập vào danh bạ của bạn"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Vị trí"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"CHIA SẺ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TỪ CHỐI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Thay đổi bàn phím"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Bàn phím khác"</string>
<string name="show_ime" msgid="2506087537466597099">"Tiếp tục sử dụng ứng dụng trên màn hình trong khi bàn phím thực đang hoạt động"</string>
<string name="hardware" msgid="194658061510127999">"Hiển thị bàn phím ảo"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Định cấu hình bàn phím thực"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Nhấn để chọn ngôn ngữ và bố cục"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ứng viên"</u></string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index f7bcaba0d8e5..3b26e461f7b1 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"内容已隐藏(根据政策规定)"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"切换到“个人”"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"切换到“工作”"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"通讯录"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"访问您的通讯录"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"位置信息"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒绝"</string>
<string name="select_input_method" msgid="8547250819326693584">"更改键盘"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"其他键盘"</string>
<string name="show_ime" msgid="2506087537466597099">"连接到实体键盘时使其在屏幕上保持显示状态"</string>
<string name="hardware" msgid="194658061510127999">"显示虚拟键盘"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"配置实体键盘"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"点按即可选择语言和布局"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"候选"</u></string>
@@ -1478,7 +1473,7 @@
<string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"已被管理员删除"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,节电助手会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n节电助手会在设备充电时自动关闭。"</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,省电模式会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n省电模式会在设备充电时自动关闭。"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
<item quantity="other">%1$d 分钟(到<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="one">1 分钟(到<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 15e9a5e18b8e..28f2bac20af8 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"已根據政策隱藏內容"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"切換至工作設定檔"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"通訊錄"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"存取您的通訊錄"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"位置"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒絕"</string>
<string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"其他鍵盤"</string>
<string name="show_ime" msgid="2506087537466597099">"在實體鍵盤處於連接狀態時保持顯示"</string>
<string name="hardware" msgid="194658061510127999">"顯示虛擬鍵盤"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"設定實體鍵盤"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕按即可選取語言和鍵盤配置"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"待選項目"</u></string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a27f1b76de0d..dfc78902c6f8 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"內容已依據政策隱藏"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"切換至公司設定檔"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"聯絡人"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"存取您的聯絡人"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"位置"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒絕"</string>
<string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"其他鍵盤"</string>
<string name="show_ime" msgid="2506087537466597099">"有連接的實體鍵盤時保持顯示"</string>
<string name="hardware" msgid="194658061510127999">"顯示虛擬鍵盤"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"設定實體鍵盤"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕觸即可選取語言和版面配置"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"待選項目"</u></string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 60be8fd9046a..e32f26bf7c89 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -233,10 +233,8 @@
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Okuqukethwe kufihlwe inqubomgomo"</string>
<string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
<string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
- <!-- no translation found for user_owner_label (1119010402169916617) -->
- <skip />
- <!-- no translation found for managed_profile_label (5289992269827577857) -->
- <skip />
+ <string name="user_owner_label" msgid="1119010402169916617">"Shintshela komuntu siqu"</string>
+ <string name="managed_profile_label" msgid="5289992269827577857">"Shintshela kumsebenzi"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Oxhumana nabo"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"finyelela koxhumana nabo"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Indawo"</string>
@@ -1063,13 +1061,10 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"YABELANA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"YENQABA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Shintsha ikhibhodi"</string>
- <string name="configure_input_methods" msgid="5673193194563164021">"Amanye amakhibhodi"</string>
<string name="show_ime" msgid="2506087537466597099">"Yigcine kusikrini ngenkathi kusebenza ikhibhodi ephathekayo"</string>
<string name="hardware" msgid="194658061510127999">"Bonisa ikhibhodi ebonakalayo"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Lungisa ikhibhodi yoqobo"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Thepha ukuze ukhethe ulimi nesakhiwo"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"abahlanganyeli"</u></string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index dbe3dcaa6344..b4371c189d40 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2504,4 +2504,20 @@
<!-- True if the device requires AppWidgetService even if it does not have
the PackageManager.FEATURE_APP_WIDGETS feature -->
<bool name="config_enableAppWidgetService">false</bool>
+
+ <!-- True if the device supports Sustained Performance Mode-->
+ <bool name="config_sustainedPerformanceModeSupported">false</bool>
+
+ <!-- Controls how we deal with externally connected physical keyboards.
+ 0 - When using this device, it is not clear for users to recognize when the physical
+ keyboard is (should be) connected and when it is (should be) disconnected. Most of
+ phones and tablets with Bluetooth keyboard would fall into this category because the
+ connected Bluetooth keyboard may or may not be nearby the host device.
+ 1 - When using this device, it is clear for users to recognize when the physical
+ keyboard is (should be) connected and when it is (should be) disconnected.
+ Devices with wired USB keyboard is one clear example. Some 2-in-1 convertible
+ tablets with dedicated keyboards may have the same affordance to wired USB keyboard.
+ -->
+ <integer name="config_externalHardKeyboardBehavior">0</integer>
+
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0839187c48d1..6ff7139ecd88 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2716,6 +2716,8 @@
<public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
<public type="style" name="Widget.Material.SeekBar.Discrete" />
+ <public type="style" name="Widget.Material.CompoundButton.Switch" />
+ <public type="style" name="Widget.Material.Light.CompoundButton.Switch" />
<public type="id" name="accessibilityActionSetProgress" />
<public type="id" name="icon_frame" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7d19e99f65eb..2215bd42db1e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1744,6 +1744,7 @@
<java-symbol type="integer" name="config_defaultNotificationLedOff" />
<java-symbol type="integer" name="config_defaultNotificationLedOn" />
<java-symbol type="integer" name="config_deskDockKeepsScreenOn" />
+ <java-symbol type="integer" name="config_externalHardKeyboardBehavior" />
<java-symbol type="integer" name="config_lightSensorWarmupTime" />
<java-symbol type="integer" name="config_lowBatteryCloseWarningBump" />
<java-symbol type="integer" name="config_lowBatteryWarningLevel" />
@@ -2419,13 +2420,11 @@
<java-symbol type="string" name="notification_hidden_text" />
<java-symbol type="string" name="notification_hidden_by_policy_text" />
<java-symbol type="id" name="app_name_text" />
- <java-symbol type="id" name="header_sub_text" />
+ <java-symbol type="id" name="header_text" />
<java-symbol type="id" name="expand_button" />
<java-symbol type="id" name="notification_header" />
- <java-symbol type="id" name="header_content_info" />
<java-symbol type="id" name="time_divider" />
- <java-symbol type="id" name="sub_text_divider" />
- <java-symbol type="id" name="content_info_divider" />
+ <java-symbol type="id" name="header_text_divider" />
<java-symbol type="id" name="text_line_1" />
<java-symbol type="drawable" name="ic_expand_notification" />
<java-symbol type="drawable" name="ic_collapse_notification" />
@@ -2542,4 +2541,6 @@
<java-symbol type="id" name="textSpacerNoTitle" />
<java-symbol type="id" name="titleDividerNoCustom" />
+
+ <java-symbol type="bool" name="config_sustainedPerformanceModeSupported" />
</resources>
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index 76b5fe1e1b55..2e593a3dc6e8 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -94,11 +94,27 @@
<!-- This is the battery capacity in mAh (measured at nominal voltage) -->
<item name="battery.capacity">1000</item>
+ <!-- Wifi related values. -->
+ <!-- Idle Receive current for wifi radio in mA. 0 by default-->
+ <item name="wifi.controller.idle">0</item>
+ <!-- Rx current for wifi radio in mA. 0 by default-->
+ <item name="wifi.controller.rx">0</item>
+ <!-- Tx current for wifi radio in mA. 0 by default-->
+ <item name="wifi.controller.tx">0</item>
+ <!-- Current at each of the wifi Tx levels in mA. The number of tx levels varies per device
+ and is available only of wifi chipsets which support the tx level reporting. Use
+ wifi.tx for other chipsets. none by default -->
+ <array name="wifi.controller.tx_levels"> <!-- mA -->
+ </array>
+ <!-- Operating volatage for wifi radio in mV. 0 by default-->
+ <item name="wifi.controller.voltage">0</item>
+
<array name="wifi.batchedscan"> <!-- mA -->
- <value>.0002</value> <!-- 1-8/hr -->
- <value>.002</value> <!-- 9-64/hr -->
- <value>.02</value> <!-- 65-512/hr -->
- <value>.2</value> <!-- 513-4,096/hr -->
- <value>2</value> <!-- 4097-/hr -->
+ <value>.0002</value> <!-- 1-8/hr -->
+ <value>.002</value> <!-- 9-64/hr -->
+ <value>.02</value> <!-- 65-512/hr -->
+ <value>.2</value> <!-- 513-4,096/hr -->
+ <value>2</value> <!-- 4097-/hr -->
</array>
+
</device>
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 9ab62cc03bea..e7aca78a0720 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -23,10 +23,10 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.os.UserHandle;
import android.test.InstrumentationTestCase;
-import android.util.Pair;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
@@ -58,25 +58,26 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
public void testGetAllValidScorers() throws Exception {
// Package 1 - Valid scorer.
- Pair<ResolveInfo, ResolveInfo> package1 = buildResolveInfo("package1", 1, true, true,
- false);
+ ResolveInfoHolder package1 = buildResolveInfo("package1", 1, true, true, false, false);
// Package 2 - Receiver does not have BROADCAST_NETWORK_PRIVILEGED permission.
- Pair<ResolveInfo, ResolveInfo> package2 = buildResolveInfo("package2", 2, false, true,
- false);
+ ResolveInfoHolder package2 = buildResolveInfo("package2", 2, false, true, false, false);
// Package 3 - App does not have SCORE_NETWORKS permission.
- Pair<ResolveInfo, ResolveInfo> package3 = buildResolveInfo("package3", 3, true, false,
- false);
+ ResolveInfoHolder package3 = buildResolveInfo("package3", 3, true, false, false, false);
// Package 4 - Valid scorer w/ optional config activity.
- Pair<ResolveInfo, ResolveInfo> package4 = buildResolveInfo("package4", 4, true, true, true);
+ ResolveInfoHolder package4 = buildResolveInfo("package4", 4, true, true, true, false);
- List<Pair<ResolveInfo, ResolveInfo>> scorers = new ArrayList<>();
+ // Package 5 - Valid scorer w/ optional service to bind to.
+ ResolveInfoHolder package5 = buildResolveInfo("package5", 5, true, true, false, true);
+
+ List<ResolveInfoHolder> scorers = new ArrayList<>();
scorers.add(package1);
scorers.add(package2);
scorers.add(package3);
scorers.add(package4);
+ scorers.add(package5);
setScorers(scorers);
Iterator<NetworkScorerAppData> result =
@@ -94,14 +95,20 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
assertEquals(4, next.mPackageUid);
assertEquals(".ConfigActivity", next.mConfigurationActivityClassName);
+ assertTrue(result.hasNext());
+ next = result.next();
+ assertEquals("package5", next.mPackageName);
+ assertEquals(5, next.mPackageUid);
+ assertEquals(".ScoringService", next.mScoringServiceClassName);
+
assertFalse(result.hasNext());
}
- private void setScorers(List<Pair<ResolveInfo, ResolveInfo>> scorers) {
+ private void setScorers(List<ResolveInfoHolder> scorers) {
List<ResolveInfo> receivers = new ArrayList<>();
- for (final Pair<ResolveInfo, ResolveInfo> scorer : scorers) {
- receivers.add(scorer.first);
- if (scorer.second != null) {
+ for (final ResolveInfoHolder scorer : scorers) {
+ receivers.add(scorer.scorerResolveInfo);
+ if (scorer.configActivityResolveInfo != null) {
// This scorer has a config activity.
Mockito.when(mMockPm.queryIntentActivities(
Mockito.argThat(new ArgumentMatcher<Intent>() {
@@ -110,10 +117,26 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
Intent intent = (Intent) object;
return NetworkScoreManager.ACTION_CUSTOM_ENABLE.equals(
intent.getAction())
- && scorer.first.activityInfo.packageName.equals(
+ && scorer.scorerResolveInfo.activityInfo.packageName.equals(
intent.getPackage());
}
- }), Mockito.eq(0))).thenReturn(Collections.singletonList(scorer.second));
+ }), Mockito.eq(0))).thenReturn(
+ Collections.singletonList(scorer.configActivityResolveInfo));
+ }
+
+ if (scorer.serviceResolveInfo != null) {
+ // This scorer has a service to bind to
+ Mockito.when(mMockPm.resolveService(
+ Mockito.argThat(new ArgumentMatcher<Intent>() {
+ @Override
+ public boolean matches(Object object) {
+ Intent intent = (Intent) object;
+ return NetworkScoreManager.ACTION_SCORE_NETWORKS.equals(
+ intent.getAction())
+ && scorer.scorerResolveInfo.activityInfo.packageName.equals(
+ intent.getPackage());
+ }
+ }), Mockito.eq(0))).thenReturn(scorer.serviceResolveInfo);
}
}
@@ -128,9 +151,9 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
.thenReturn(receivers);
}
- private Pair<ResolveInfo, ResolveInfo> buildResolveInfo(String packageName, int packageUid,
- boolean hasReceiverPermission, boolean hasScorePermission, boolean hasConfigActivity)
- throws Exception {
+ private ResolveInfoHolder buildResolveInfo(String packageName, int packageUid,
+ boolean hasReceiverPermission, boolean hasScorePermission, boolean hasConfigActivity,
+ boolean hasServiceInfo) throws Exception {
Mockito.when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
.thenReturn(hasScorePermission ?
PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
@@ -150,6 +173,27 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
configActivityInfo.activityInfo = new ActivityInfo();
configActivityInfo.activityInfo.name = ".ConfigActivity";
}
- return Pair.create(resolveInfo, configActivityInfo);
+
+ ResolveInfo serviceInfo = null;
+ if (hasServiceInfo) {
+ serviceInfo = new ResolveInfo();
+ serviceInfo.serviceInfo = new ServiceInfo();
+ serviceInfo.serviceInfo.name = ".ScoringService";
+ }
+
+ return new ResolveInfoHolder(resolveInfo, configActivityInfo, serviceInfo);
+ }
+
+ private static class ResolveInfoHolder {
+ final ResolveInfo scorerResolveInfo;
+ final ResolveInfo configActivityResolveInfo;
+ final ResolveInfo serviceResolveInfo;
+
+ public ResolveInfoHolder(ResolveInfo scorerResolveInfo,
+ ResolveInfo configActivityResolveInfo, ResolveInfo serviceResolveInfo) {
+ this.scorerResolveInfo = scorerResolveInfo;
+ this.configActivityResolveInfo = configActivityResolveInfo;
+ this.serviceResolveInfo = serviceResolveInfo;
+ }
}
}
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index 43a61e301c8f..d491ec4111fb 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -515,7 +515,7 @@ public class IPrintManagerParametersTest extends BasePrintTest {
public void testGetPrintServices() throws Exception {
List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
PrintManager.ALL_SERVICES, mUserId);
- assertTrue(printServices.size() >= 2);
+ assertTrue(printServices.size() >= 1);
printServices = mIPrintManager.getPrintServices(0, mUserId);
assertEquals(printServices, null);
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
index 59ffd566909f..eafe42723780 100644
--- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -16,13 +16,35 @@
package android.widget;
-import android.app.Activity;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.Espresso.pressBack;
+import static android.support.test.espresso.action.ViewActions.clearText;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.action.ViewActions.replaceText;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static android.widget.espresso.DragHandleUtils.onHandleView;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupContainsItem;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsDisplayed;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsNotDisplayed;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.clickSuggestionsPopupItem;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.onSuggestionsPopup;
+import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
+import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
+import static org.hamcrest.Matchers.is;
import android.content.res.TypedArray;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewAssertion;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.Suppress;
import android.text.Selection;
-import android.text.SpannableStringBuilder;
+import android.text.Spannable;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.SuggestionSpan;
@@ -42,55 +64,215 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2
super(TextViewActivity.class);
}
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ getActivity();
+ }
+
+ private void setSuggestionSpan(SuggestionSpan span, int start, int end) {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ textView.post(
+ () -> {
+ final Spannable text = (Spannable) textView.getText();
+ text.setSpan(span, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ Selection.setSelection(text, (start + end) / 2);
+ });
+ getInstrumentation().waitForIdleSync();
+ }
+
+ @SmallTest
+ public void testOnTextContextMenuItem() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE));
+ getInstrumentation().waitForIdleSync();
+
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ @SmallTest
+ public void testSelectionActionMode() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('e')));
+ sleepForFloatingToolbarPopup();
+ assertFloatingToolbarContainsItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+ sleepForFloatingToolbarPopup();
+ clickFloatingToolbarItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ @SmallTest
+ public void testInsertionActionMode() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+ onHandleView(com.android.internal.R.id.insertion_handle).perform(click());
+ sleepForFloatingToolbarPopup();
+ assertFloatingToolbarContainsItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+ clickFloatingToolbarItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ private void showSuggestionsPopup() {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE));
+ getInstrumentation().waitForIdleSync();
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ @SmallTest
+ public void testSuggestionItems() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ showSuggestionsPopup();
+
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("DEF");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Select an item.
+ clickSuggestionsPopupItem("DEF");
+ assertSuggestionsPopupIsNotDisplayed();
+ onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi")));
+
+ showSuggestionsPopup();
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("def");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Delete
+ clickSuggestionsPopupItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+ assertSuggestionsPopupIsNotDisplayed();
+ onView(withId(R.id.textview)).check(matches(withText("abc ghi")));
+ }
+
+ @SmallTest
+ public void testMisspelled() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_MISSPELLED);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ showSuggestionsPopup();
+
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("DEF");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.addToDictionary));
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Click "Add to dictionary".
+ clickSuggestionsPopupItem(
+ getActivity().getString(com.android.internal.R.string.addToDictionary));
+ // TODO: Check if add to dictionary dialog is displayed.
+ }
+
+ @SmallTest
+ public void testEasyCorrect() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"},
+ SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("DEF");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Select an item.
+ clickSuggestionsPopupItem("DEF");
+ assertSuggestionsPopupIsNotDisplayed();
+ onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi")));
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+ assertSuggestionsPopupIsNotDisplayed();
+
+ showSuggestionsPopup();
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("def");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+ }
+
@SmallTest
- @Suppress
public void testTextAppearanceInSuggestionsPopup() {
- final Activity activity = getActivity();
+ final String text = "abc def ghi";
- final String sampleText = "abc def ghi";
final String[] singleWordCandidates = {"DEF", "Def"};
- final SuggestionSpan singleWordSuggestionSpan = new SuggestionSpan(activity,
- singleWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION);
- final int singleWordSpanStart = 4;
- final int singleWordSpanEnd = 7;
-
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ singleWordCandidates, SuggestionSpan.FLAG_MISSPELLED);
final String[] multiWordCandidates = {"ABC DEF GHI", "Abc Def Ghi"};
- final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(activity,
- multiWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION);
- final int multiWordSpanStart = 0;
- final int multiWordSpanEnd = 11;
+ final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(getActivity(),
+ multiWordCandidates, SuggestionSpan.FLAG_MISSPELLED);
- TypedArray array = activity.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
- int id = array.getResourceId(
+ final TypedArray array =
+ getActivity().obtainStyledAttributes(com.android.internal.R.styleable.Theme);
+ final int id = array.getResourceId(
com.android.internal.R.styleable.Theme_textEditSuggestionHighlightStyle, 0);
array.recycle();
-
- TextAppearanceSpan expectedSpan = new TextAppearanceSpan(activity, id);
- TextPaint tmpTp = new TextPaint();
+ final TextAppearanceSpan expectedSpan = new TextAppearanceSpan(getActivity(), id);
+ final TextPaint tmpTp = new TextPaint();
expectedSpan.updateDrawState(tmpTp);
final int expectedHighlightTextColor = tmpTp.getColor();
final float expectedHighlightTextSize = tmpTp.getTextSize();
-
- final EditText editText = (EditText) activity.findViewById(R.id.textview);
- final Editor editor = editText.getEditorForTesting();
- assertNotNull(editor);
-
- // Request to show SuggestionsPopupWindow.
- Runnable showSuggestionWindowRunner = new Runnable() {
- @Override
- public void run() {
- SpannableStringBuilder ssb = new SpannableStringBuilder();
- ssb.append(sampleText);
- ssb.setSpan(singleWordSuggestionSpan, singleWordSpanStart, singleWordSpanEnd,
- Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- ssb.setSpan(multiWordSuggestionSpan, multiWordSpanStart, multiWordSpanEnd,
- Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- editText.setText(ssb);
-
- Selection.setSelection(editText.getText(), singleWordSpanStart, singleWordSpanEnd);
- editText.onTextContextMenuItem(TextView.ID_REPLACE);
- }
- };
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
// In this test, the SuggestionsPopupWindow looks like
// abc def ghi
@@ -103,96 +285,74 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2
// | DELETE |
// -----------------
// *XX* means that XX is highlighted.
- Runnable popupVaridator = new Runnable() {
- @Override
- public void run() {
- Editor.SuggestionsPopupWindow popupWindow =
- editor.getSuggestionsPopupWindowForTesting();
- assertNotNull(popupWindow);
-
- LinearLayout linearLayout = (LinearLayout) popupWindow.getContentViewForTesting();
- assertNotNull(linearLayout);
-
- ListView listView = (ListView)linearLayout.findViewById(
- com.android.internal.R.id.suggestionContainer);
- assertNotNull(listView);
-
- int childNum = listView.getChildCount();
- assertEquals(singleWordCandidates.length + multiWordCandidates.length, childNum);
-
- for (int i = 0; i < singleWordCandidates.length; ++i) {
- TextView textView = (TextView) listView.getChildAt(i);
- assertNotNull(textView);
-
- Spanned spanned = (Spanned) textView.getText();
- assertNotNull(spanned);
-
- // Check that the suggestion item order is kept.
- String expectedText = "abc " + singleWordCandidates[i] + " ghi";
- assertEquals(expectedText, spanned.toString());
-
- // Check that the text is highlighted with correct color and text size.
- TextAppearanceSpan[] taSpan = spanned.getSpans(singleWordSpanStart,
- singleWordSpanEnd, TextAppearanceSpan.class);
- assertEquals(1, taSpan.length);
- TextPaint tp = new TextPaint();
- taSpan[0].updateDrawState(tp);
- assertEquals(expectedHighlightTextColor, tp.getColor());
- assertEquals(expectedHighlightTextSize, tp.getTextSize());
-
- // Check only center word is highlighted.
- assertEquals(singleWordSpanStart, spanned.getSpanStart(taSpan[0]));
- assertEquals(singleWordSpanEnd, spanned.getSpanEnd(taSpan[0]));
- }
+ for (int i = 0; i < 2; i++) {
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+ setSuggestionSpan(multiWordSuggestionSpan, 0, text.length());
- for (int i = 0; i < multiWordCandidates.length; ++i) {
- int indexInListView = singleWordCandidates.length + i;
- TextView textView = (TextView) listView.getChildAt(indexInListView);
- assertNotNull(textView);
-
- Spanned spanned = (Spanned) textView.getText();
- assertNotNull(spanned);
-
- // Check that the suggestion item order is kept.
- assertEquals(multiWordCandidates[i], spanned.toString());
-
- // Check that the text is highlighted with correct color and text size.
- TextAppearanceSpan[] taSpan = spanned.getSpans(
- 0, multiWordCandidates[i].length(), TextAppearanceSpan.class);
- assertEquals(1, taSpan.length);
- TextPaint tp = new TextPaint();
- taSpan[0].updateDrawState(tp);
- assertEquals(expectedHighlightTextColor, tp.getColor());
- assertEquals(expectedHighlightTextSize, tp.getTextSize());
-
- // Check the whole text is highlighted.
- assertEquals(multiWordSpanStart, spanned.getSpanStart(taSpan[0]));
- assertEquals(multiWordSpanEnd, spanned.getSpanEnd(taSpan[0]));
- }
+ showSuggestionsPopup();
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("abc DEF ghi");
+ assertSuggestionsPopupContainsItem("abc Def ghi");
+ assertSuggestionsPopupContainsItem("ABC DEF GHI");
+ assertSuggestionsPopupContainsItem("Abc Def Ghi");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
- TextView deleteButton = (TextView)linearLayout.findViewById(
- com.android.internal.R.id.deleteButton);
- assertEquals(View.VISIBLE, deleteButton.getWindowVisibility());
- }
- };
+ onSuggestionsPopup().check(new ViewAssertion() {
+ @Override
+ public void check(View view, NoMatchingViewException e) {
+ final ListView listView = (ListView) view.findViewById(
+ com.android.internal.R.id.suggestionContainer);
+ assertNotNull(listView);
+ final int childNum = listView.getChildCount();
+ assertEquals(singleWordCandidates.length + multiWordCandidates.length,
+ childNum);
- // Show the SuggestionWindow and verify the contents.
- activity.runOnUiThread(showSuggestionWindowRunner);
- getInstrumentation().waitForIdleSync();
- activity.runOnUiThread(popupVaridator);
-
- // Request to hide the SuggestionPopupWindow and wait until it is hidden.
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- editText.setText("");
- }
- });
- getInstrumentation().waitForIdleSync();
+ for (int j = 0; j < childNum; j++) {
+ final TextView suggestion = (TextView) listView.getChildAt(j);
+ assertNotNull(suggestion);
+ final Spanned spanned = (Spanned) suggestion.getText();
+ assertNotNull(spanned);
- // Show and verify the contents again.
- activity.runOnUiThread(showSuggestionWindowRunner);
- getInstrumentation().waitForIdleSync();
- activity.runOnUiThread(popupVaridator);
+ // Check that the suggestion item order is kept.
+ final String expectedText;
+ if (j < singleWordCandidates.length) {
+ expectedText = "abc " + singleWordCandidates[j] + " ghi";
+ } else {
+ expectedText = multiWordCandidates[j - singleWordCandidates.length];
+ }
+ assertEquals(expectedText, spanned.toString());
+
+ // Check that the text is highlighted with correct color and text size.
+ final TextAppearanceSpan[] taSpan = spanned.getSpans(
+ text.indexOf('d'), text.indexOf('f') + 1, TextAppearanceSpan.class);
+ assertEquals(1, taSpan.length);
+ TextPaint tp = new TextPaint();
+ taSpan[0].updateDrawState(tp);
+ assertEquals(expectedHighlightTextColor, tp.getColor());
+ assertEquals(expectedHighlightTextSize, tp.getTextSize());
+
+ // Check the correct part of the text is highlighted.
+ final int expectedStart;
+ final int expectedEnd;
+ if (j < singleWordCandidates.length) {
+ expectedStart = text.indexOf('d');
+ expectedEnd = text.indexOf('f') + 1;
+ } else {
+ expectedStart = 0;
+ expectedEnd = text.length();
+ }
+ assertEquals(expectedStart, spanned.getSpanStart(taSpan[0]));
+ assertEquals(expectedEnd, spanned.getSpanEnd(taSpan[0]));
+ }
+ }
+ });
+ pressBack();
+ onView(withId(R.id.textview))
+ .inRoot(withDecorView(is(getActivity().getWindow().getDecorView())))
+ .perform(clearText());
+ }
}
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index 923b8299a60a..edb749b95b10 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -16,6 +16,10 @@
package android.widget;
+
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemDisabled;
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemEnabled;
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuIsNotDisplayed;
import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
import static android.widget.espresso.TextViewActions.mouseClickOnTextAtIndex;
@@ -41,11 +45,9 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText;
import com.android.frameworks.coretests.R;
-import android.support.test.espresso.Espresso;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.MotionEvent;
-import android.widget.espresso.ContextMenuUtils;
/**
* Tests mouse interaction of the TextView widget from an Activity
@@ -57,7 +59,8 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2<
}
@Override
- public void setUp() {
+ public void setUp() throws Exception {
+ super.setUp();
getActivity();
}
@@ -102,28 +105,28 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2<
onView(withId(R.id.textview)).perform(click());
onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text));
- ContextMenuUtils.assertContextMenuIsNotDisplayed();
+ assertContextMenuIsNotDisplayed();
onView(withId(R.id.textview)).perform(
mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY));
- ContextMenuUtils.assertContextMenuContainsItemDisabled(
+ assertContextMenuContainsItemDisabled(
getActivity().getString(com.android.internal.R.string.copy));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.undo));
// Hide context menu.
pressBack();
- ContextMenuUtils.assertContextMenuIsNotDisplayed();
+ assertContextMenuIsNotDisplayed();
onView(withId(R.id.textview)).perform(
mouseDragOnText(text.indexOf("c"), text.indexOf("h")));
onView(withId(R.id.textview)).perform(
mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.copy));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.undo));
// Hide context menu.
@@ -133,9 +136,9 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2<
onView(withId(R.id.textview)).perform(
mouseClickOnTextAtIndex(text.indexOf("i"), MotionEvent.BUTTON_SECONDARY));
- ContextMenuUtils.assertContextMenuContainsItemDisabled(
+ assertContextMenuContainsItemDisabled(
getActivity().getString(com.android.internal.R.string.copy));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.undo));
// Hide context menu.
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index f779d6cee976..67ffd2b0ca3b 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -19,7 +19,6 @@ package android.widget;
import static android.support.test.espresso.action.ViewActions.longClick;
import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
-import static android.widget.espresso.FloatingToolbarEspressoUtils.onFloatingToolBarItem;
import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex;
@@ -31,9 +30,10 @@ import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIn
import static android.widget.espresso.TextViewAssertions.hasSelection;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed;
-import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.pressKey;
@@ -67,7 +67,8 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
}
@Override
- public void setUp() {
+ public void setUp() throws Exception {
+ super.setUp();
getActivity();
}
@@ -256,7 +257,8 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
onView(withId(R.id.textview)).perform(typeTextIntoFocusedView("test"));
onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1));
- onFloatingToolBarItem(withText(com.android.internal.R.string.cut)).perform(click());
+ clickFloatingToolbarItem(
+ getActivity().getString(com.android.internal.R.string.cut));
onView(withId(R.id.textview)).perform(longClick());
sleepForFloatingToolbarPopup();
@@ -675,4 +677,26 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
assertFloatingToolbarContainsItem(
getActivity().getString(com.android.internal.R.string.copy));
}
+
+ @SmallTest
+ public void testTransientState() throws Exception {
+ final String text = "abc def";
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ assertFalse(textView.hasTransientState());
+
+ onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('b')));
+ // hasTransientState should return true when user generated selection is active.
+ assertTrue(textView.hasTransientState());
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('d')));
+ // hasTransientState should return false as the selection has been cleared.
+ assertFalse(textView.hasTransientState());
+ textView.post(
+ () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length()));
+ getInstrumentation().waitForIdleSync();
+ // hasTransientState should return false when selection is created by API.
+ assertFalse(textView.hasTransientState());
+ }
}
diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
index 0f7f359447ad..838f4db76165 100644
--- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
+++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
@@ -17,6 +17,7 @@
package android.widget.espresso;
import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
@@ -24,6 +25,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withTagValue;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;
@@ -34,8 +36,6 @@ import android.support.test.espresso.NoMatchingViewException;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewInteraction;
-import android.support.test.espresso.action.ViewActions;
-import android.support.test.espresso.matcher.ViewMatchers;
import android.view.View;
import com.android.internal.widget.FloatingToolbar;
@@ -90,7 +90,7 @@ public class FloatingToolbarEspressoUtils {
final int id = com.android.internal.R.id.overflow;
onView(allOf(withId(id), isDisplayed()))
.inRoot(withDecorView(hasDescendant(withId(id))))
- .perform(ViewActions.click());
+ .perform(click());
onView(isRoot()).perform(SLEEP);
}
@@ -106,7 +106,7 @@ public class FloatingToolbarEspressoUtils {
*/
public static void assertFloatingToolbarContainsItem(String itemLabel) {
try{
- onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel))));
+ onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel))));
} catch (AssertionError e) {
try{
toggleOverflow();
@@ -115,7 +115,7 @@ public class FloatingToolbarEspressoUtils {
throw e;
}
try{
- onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel))));
+ onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel))));
} finally {
toggleOverflow();
}
@@ -138,6 +138,21 @@ public class FloatingToolbarEspressoUtils {
}
/**
+ * Click specified item on the floating tool bar.
+ *
+ * @param itemLabel label of the item.
+ */
+ public static void clickFloatingToolbarItem(String itemLabel) {
+ try{
+ onFloatingToolBarItem(withText(itemLabel)).check(matches(isDisplayed()));
+ } catch (AssertionError e) {
+ // Try to find the item in the overflow menu.
+ toggleOverflow();
+ }
+ onFloatingToolBarItem(withText(itemLabel)).perform(click());
+ }
+
+ /**
* ViewAction to sleep to wait floating toolbar's animation.
*/
private static final ViewAction SLEEP = new ViewAction() {
diff --git a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java
index b8ea2de3abfd..bec4180cc1f4 100644
--- a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java
+++ b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java
@@ -21,7 +21,6 @@ import org.hamcrest.Matcher;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.action.CoordinatesProvider;
-import android.support.test.espresso.action.GeneralClickAction;
import android.support.test.espresso.action.MotionEvents;
import android.support.test.espresso.action.MotionEvents.DownResultHolder;
import android.support.test.espresso.action.Press;
@@ -34,7 +33,7 @@ import android.view.ViewConfiguration;
* ViewAction for performing an click on View by a mouse.
*/
public final class MouseClickAction implements ViewAction {
- private final GeneralClickAction mGeneralClickAction;
+ private final ViewClickAction mViewClickAction;
@MouseUiController.MouseButton
private final int mButton;
@@ -100,30 +99,22 @@ public final class MouseClickAction implements ViewAction {
*/
public MouseClickAction(Tapper tapper, CoordinatesProvider coordinatesProvider,
@MouseUiController.MouseButton int button) {
- mGeneralClickAction = new GeneralClickAction(tapper, coordinatesProvider, Press.PINPOINT);
+ mViewClickAction = new ViewClickAction(tapper, coordinatesProvider, Press.PINPOINT);
mButton = button;
}
@Override
public Matcher<View> getConstraints() {
- return mGeneralClickAction.getConstraints();
+ return mViewClickAction.getConstraints();
}
@Override
public String getDescription() {
- return mGeneralClickAction.getDescription();
+ return mViewClickAction.getDescription();
}
@Override
public void perform(UiController uiController, View view) {
- mGeneralClickAction.perform(new MouseUiController(uiController, mButton), view);
- long doubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
- if (0 < doubleTapTimeout) {
- // Wait to avoid false gesture detection. Without this wait, consecutive clicks can be
- // detected as a triple click. e.g. 2 double clicks are detected as a triple click and
- // a single click because espresso isn't aware of triple click detection logic, which
- // is TextView specific gesture.
- uiController.loopMainThreadForAtLeast(doubleTapTimeout);
- }
+ mViewClickAction.perform(new MouseUiController(uiController, mButton), view);
}
}
diff --git a/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java
new file mode 100644
index 000000000000..b5a96ae6c49a
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.widget.espresso;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import org.hamcrest.Matcher;
+
+import android.support.test.espresso.NoMatchingRootException;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.ViewInteraction;
+import android.support.test.espresso.action.GeneralLocation;
+import android.support.test.espresso.action.Press;
+import android.support.test.espresso.action.Tap;
+import android.view.View;
+
+public final class SuggestionsPopupwindowUtils {
+ private static final int id = com.android.internal.R.id.suggestionWindowContainer;
+
+ private SuggestionsPopupwindowUtils() {};
+
+ public static ViewInteraction onSuggestionsPopup() {
+ return onView(withId(id)).inRoot(withDecorView(hasDescendant(withId(id))));
+ }
+
+ private static ViewInteraction onSuggestionsPopupItem(Matcher<View> matcher) {
+ return onView(matcher).inRoot(withDecorView(hasDescendant(withId(id))));
+ }
+
+ /**
+ * Asserts that the suggestions popup is displayed on screen.
+ *
+ * @throws AssertionError if the assertion fails
+ */
+ public static void assertSuggestionsPopupIsDisplayed() {
+ onSuggestionsPopup().check(matches(isDisplayed()));
+ }
+
+ /**
+ * Asserts that the suggestions popup is not displayed on screen.
+ *
+ * @throws AssertionError if the assertion fails
+ */
+ public static void assertSuggestionsPopupIsNotDisplayed() {
+ try {
+ onSuggestionsPopup().check(matches(isDisplayed()));
+ } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) {
+ return;
+ }
+ throw new AssertionError("Suggestions popup is displayed");
+ }
+
+ /**
+ * Asserts that the suggestions popup contains the specified item.
+ *
+ * @param itemLabel label of the item.
+ * @throws AssertionError if the assertion fails
+ */
+ public static void assertSuggestionsPopupContainsItem(String itemLabel) {
+ onSuggestionsPopupItem(withText(itemLabel)).check(matches(isDisplayed()));
+ }
+
+ /**
+ * Click on the specified item in the suggestions popup.
+ *
+ * @param itemLabel label of the item.
+ */
+ public static void clickSuggestionsPopupItem(String itemLabel) {
+ onSuggestionsPopupItem(withText(itemLabel)).perform(new SuggestionItemClickAction());
+ }
+
+ /**
+ * Click action to avoid checking ViewClickAction#getConstraints().
+ * TODO: Use Espresso.onData instead of this.
+ */
+ private static final class SuggestionItemClickAction implements ViewAction {
+ private final ViewClickAction mViewClickAction;
+
+ public SuggestionItemClickAction() {
+ mViewClickAction =
+ new ViewClickAction(Tap.SINGLE, GeneralLocation.VISIBLE_CENTER, Press.FINGER);
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return mViewClickAction.getDescription();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mViewClickAction.perform(uiController, view);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
index 4cecb65f5fa3..335d021efd14 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
@@ -17,15 +17,10 @@
package android.widget.espresso;
import static android.support.test.espresso.action.ViewActions.actionWithAssertions;
-
-import org.hamcrest.core.Is;
-import org.hamcrest.core.IsInstanceOf;
-
import android.graphics.Rect;
import android.support.test.espresso.PerformException;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.action.CoordinatesProvider;
-import android.support.test.espresso.action.GeneralClickAction;
import android.support.test.espresso.action.Press;
import android.support.test.espresso.action.Tap;
import android.support.test.espresso.util.HumanReadables;
@@ -55,7 +50,7 @@ public final class TextViewActions {
*/
public static ViewAction clickOnTextAtIndex(int index) {
return actionWithAssertions(
- new GeneralClickAction(Tap.SINGLE, new TextCoordinates(index), Press.FINGER));
+ new ViewClickAction(Tap.SINGLE, new TextCoordinates(index), Press.FINGER));
}
/**
@@ -101,7 +96,7 @@ public final class TextViewActions {
*/
public static ViewAction doubleClickOnTextAtIndex(int index) {
return actionWithAssertions(
- new GeneralClickAction(Tap.DOUBLE, new TextCoordinates(index), Press.FINGER));
+ new ViewClickAction(Tap.DOUBLE, new TextCoordinates(index), Press.FINGER));
}
/**
@@ -131,7 +126,7 @@ public final class TextViewActions {
*/
public static ViewAction longPressOnTextAtIndex(int index) {
return actionWithAssertions(
- new GeneralClickAction(Tap.LONG, new TextCoordinates(index), Press.FINGER));
+ new ViewClickAction(Tap.LONG, new TextCoordinates(index), Press.FINGER));
}
/**
diff --git a/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java b/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java
new file mode 100644
index 000000000000..8bce1b09517b
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.widget.espresso;
+
+import org.hamcrest.Matcher;
+
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.CoordinatesProvider;
+import android.support.test.espresso.action.GeneralClickAction;
+import android.support.test.espresso.action.PrecisionDescriber;
+import android.support.test.espresso.action.Tapper;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+public final class ViewClickAction implements ViewAction {
+ private final GeneralClickAction mGeneralClickAction;
+
+ public ViewClickAction(Tapper tapper, CoordinatesProvider coordinatesProvider,
+ PrecisionDescriber precisionDescriber) {
+ mGeneralClickAction = new GeneralClickAction(tapper, coordinatesProvider,
+ precisionDescriber);
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return mGeneralClickAction.getConstraints();
+ }
+
+ @Override
+ public String getDescription() {
+ return mGeneralClickAction.getDescription();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mGeneralClickAction.perform(uiController, view);
+ long doubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
+ if (0 < doubleTapTimeout) {
+ // Wait to avoid false gesture detection. Without this wait, consecutive clicks can be
+ // detected as a double click or triple click. e.g. 2 double clicks on TextView are
+ // detected as a triple click and a single click because espresso isn't aware of
+ // TextView specific gestures.
+ uiController.loopMainThreadForAtLeast(doubleTapTimeout);
+ }
+ }
+}
diff --git a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
index 5f36c2d0c29b..3cef33621a01 100644
--- a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
@@ -16,16 +16,32 @@
package com.android.internal.util;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.util.Xml;
+
import junit.framework.TestCase;
+import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
/**
* Tests for {@link FastXmlSerializer}
*/
+@SmallTest
public class FastXmlSerializerTest extends TestCase {
+ private static final String TAG = "FastXmlSerializerTest";
+
+ private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH TRUE.
+
+ private static final String ROOT_TAG = "root";
+ private static final String ATTR = "attr";
+
public void testEmptyText() throws Exception {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
@@ -44,4 +60,93 @@ public class FastXmlSerializerTest extends TestCase {
assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<string name=\"meow\"></string>\n", stream.toString());
}
+
+ private boolean checkPreserved(String description, String str) {
+ boolean ok = true;
+ byte[] data;
+ try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ final XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(baos, StandardCharsets.UTF_16.name());
+ out.startDocument(null, true);
+
+ out.startTag(null, ROOT_TAG);
+ out.attribute(null, ATTR, str);
+ out.text(str);
+ out.endTag(null, ROOT_TAG);
+
+ out.endDocument();
+ baos.flush();
+ data = baos.toByteArray();
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to serialize: " + description, e);
+ return false;
+ }
+
+ if (ENABLE_DUMP) {
+ Log.d(TAG, "Dump:");
+ Log.d(TAG, new String(data));
+ }
+
+ try (final ByteArrayInputStream baos = new ByteArrayInputStream(data)) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(baos, StandardCharsets.UTF_16.name());
+
+ int type;
+ String tag = null;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG) {
+ tag = parser.getName();
+ if (ROOT_TAG.equals(tag)) {
+ String read = parser.getAttributeValue(null, ATTR);
+ if (!str.equals(read)) {
+ Log.e(TAG, "Attribute not preserved: " + description
+ + " input=\"" + str + "\", but read=\"" + read + "\"");
+ ok = false;
+ }
+ }
+ }
+ if (type == XmlPullParser.TEXT && ROOT_TAG.equals(tag)) {
+ String read = parser.getText();
+ if (!str.equals(parser.getText())) {
+ Log.e(TAG, "Text not preserved: " + description
+ + " input=\"" + str + "\", but read=\"" + read + "\"");
+ ok = false;
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to parse: " + description, e);
+ return false;
+ }
+ return ok;
+ }
+
+ private boolean check(String description, String str) throws Exception {
+ boolean ok = false;
+ ok |= checkPreserved(description, str);
+ ok |= checkPreserved(description + " wrapped with spaces" ," " + str + " ");
+ return ok;
+ }
+
+ @LargeTest
+ public void testAllCharacters() throws Exception {
+ boolean ok = true;
+ for (int i = 0; i < 0xffff; i++) {
+ if (0xd800 <= i && i <= 0xdfff) {
+ // Surrogate pair characters.
+ continue;
+ }
+ ok &= check("char: " + i, String.valueOf((char) i));
+ }
+ // Dangling surrogate pairs. We can't preserve them.
+ assertFalse(check("+ud800", "\ud800"));
+ assertFalse(check("+udc00", "\udc00"));
+
+ for (int i = 0xd800; i < 0xdc00; i ++) {
+ for (int j = 0xdc00; j < 0xe000; j++) {
+ ok &= check("char: " + i, String.valueOf((char) i) + String.valueOf((char) j));
+ }
+ }
+ assertTrue("Some tests failed. See logcat for details.", ok);
+ }
}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index e3639ecdeeb8..f4c5b53dd36b 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -108,6 +108,6 @@ CHECK_EMOJI := true
endif
.PHONY: fontchain_lint
-fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml
+fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml $(PRODUCT_OUT)/system.img
PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \
python $(FONTCHAIN_LINTER) $(TARGET_OUT) $(CHECK_EMOJI) external/unicode
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3973f2ff428b..aa81b9196fe1 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -37,22 +37,26 @@ import java.lang.annotation.RetentionPolicy;
public final class Outline {
private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
- private static final int MODE_EMPTY = 0;
- private static final int MODE_RECT = 1;
- private static final int MODE_CONVEX_PATH = 2;
+ /** @hide */
+ public static final int MODE_EMPTY = 0;
+ /** @hide */
+ public static final int MODE_ROUND_RECT = 1;
+ /** @hide */
+ public static final int MODE_CONVEX_PATH = 2;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = false,
value = {
MODE_EMPTY,
- MODE_RECT,
+ MODE_ROUND_RECT,
MODE_CONVEX_PATH,
})
public @interface Mode {}
+ /** @hide */
@Mode
- private int mMode = MODE_EMPTY;
+ public int mMode = MODE_EMPTY;
/** @hide */
public final Path mPath = new Path();
@@ -176,7 +180,7 @@ public final class Outline {
return;
}
- mMode = MODE_RECT;
+ mMode = MODE_ROUND_RECT;
mRect.set(left, top, right, bottom);
mRadius = radius;
mPath.rewind();
@@ -199,7 +203,7 @@ public final class Outline {
* bounds, or {@code false} if no outline bounds are set
*/
public boolean getRect(@NonNull Rect outRect) {
- if (mMode != MODE_RECT) {
+ if (mMode != MODE_ROUND_RECT) {
return false;
}
outRect.set(mRect);
@@ -270,7 +274,7 @@ public final class Outline {
* Offsets the Outline by (dx,dy)
*/
public void offset(int dx, int dy) {
- if (mMode == MODE_RECT) {
+ if (mMode == MODE_ROUND_RECT) {
mRect.offset(dx, dy);
} else if (mMode == MODE_CONVEX_PATH) {
mPath.offset(dx, dy);
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 46a0f438e8a4..35385ebcd57f 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -1416,6 +1416,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
Log.d(LOGTAG, "on finished called from native");
}
mStarted = false;
+ // Invalidate in the end of the animation to make sure the data in
+ // RT thread is synced back to UI thread.
+ invalidateOwningView();
if (mListener != null) {
mListener.onAnimationEnd(null);
}
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index f43bf860946b..5fb842598046 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -809,10 +809,6 @@ void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op,
Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
.build();
renderer.renderGlop(state, glop);
-
- if (op.destroy) {
- renderer.renderState().layerPool().putOrDelete(buffer);
- }
}
}
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 20f102bac351..3c302b3f6c9f 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -37,6 +37,10 @@ OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t h
return buffer;
}
+void BakedOpRenderer::recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) {
+ mRenderState.layerPool().putOrDelete(offscreenBuffer);
+}
+
void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 1b4065aa0aa6..62bc564a4a2a 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -69,6 +69,7 @@ public:
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect);
void endFrame(const Rect& repaintRect);
WARN_UNUSED_RESULT OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height);
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer);
void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect);
void endLayer();
WARN_UNUSED_RESULT OffscreenBuffer* copyToLayer(const Rect& area);
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 59f0d7cc7346..181b3433381c 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -45,6 +45,7 @@ DisplayList::DisplayList()
, regions(stdAllocator)
, referenceHolders(stdAllocator)
, functors(stdAllocator)
+ , pushStagingFunctors(stdAllocator)
, hasDrawOps(false) {
}
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 60cc7bab64dd..e209e2a896fc 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -110,6 +110,16 @@ struct ReplayStateStruct : public PlaybackStateStruct {
};
/**
+ * Functor that can be used for objects with data in both UI thread and RT to keep the data
+ * in sync. This functor, when added to DisplayList, will be call during DisplayList sync.
+ */
+struct PushStagingFunctor {
+ PushStagingFunctor() {}
+ virtual ~PushStagingFunctor() {}
+ virtual void operator ()() {}
+};
+
+/**
* Data structure that holds the list of commands used in display list stream
*/
class DisplayList {
@@ -142,6 +152,7 @@ public:
const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
const LsaVector<Functor*>& getFunctors() const { return functors; }
+ const LsaVector<PushStagingFunctor*>& getPushStagingFunctors() { return pushStagingFunctors; }
size_t addChild(NodeOpType* childOp);
@@ -183,6 +194,11 @@ private:
// List of functors
LsaVector<Functor*> functors;
+ // List of functors that need to be notified of pushStaging. Note that this list gets nothing
+ // but a callback during sync DisplayList, unlike the list of functors defined above, which
+ // gets special treatment exclusive for webview.
+ LsaVector<PushStagingFunctor*> pushStagingFunctors;
+
bool hasDrawOps; // only used if !HWUI_NEW_OPS
void cleanupResources();
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 2dccf32a7c78..c6e92abbe0c3 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -415,7 +415,8 @@ void DisplayListCanvas::drawPoints(const float* points, int count, const SkPaint
void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
mDisplayList->ref(tree);
- addDrawOp(new (alloc()) DrawVectorDrawableOp(tree));
+ mDisplayList->pushStagingFunctors.push_back(tree->getFunctor());
+ addDrawOp(new (alloc()) DrawVectorDrawableOp(tree, tree->stagingProperties()->getBounds()));
}
void DisplayListCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count,
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 516e6199bd27..59f073ff593c 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1110,15 +1110,14 @@ private:
class DrawVectorDrawableOp : public DrawOp {
public:
- DrawVectorDrawableOp(VectorDrawableRoot* tree)
- : DrawOp(nullptr), mTree(tree) {}
+ DrawVectorDrawableOp(VectorDrawableRoot* tree, const SkRect& bounds)
+ : DrawOp(nullptr), mTree(tree), mDst(bounds) {}
virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
const SkBitmap& bitmap = mTree->getBitmapUpdateIfDirty();
SkPaint* paint = mTree->getPaint();
- const SkRect bounds = mTree->getBounds();
renderer.drawBitmap(&bitmap, Rect(0, 0, bitmap.width(), bitmap.height()),
- bounds, paint);
+ mDst, paint);
}
virtual void output(int level, uint32_t logFlags) const override {
@@ -1129,6 +1128,7 @@ public:
private:
VectorDrawableRoot* mTree;
+ SkRect mDst;
};
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 9c46c0058f68..0401f2d44776 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -522,7 +522,10 @@ static bool hasMergeableClip(const BakedOpState& state) {
void FrameBuilder::deferBitmapOp(const BitmapOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
- bakedState->setupOpacity(op.paint);
+
+ if (op.bitmap->isOpaque()) {
+ bakedState->setupOpacity(op.paint);
+ }
// Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
// Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index e41822729695..039ab6bd88ab 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -86,6 +86,7 @@ public:
*/
template <typename StaticDispatcher, typename Renderer>
void replayBakedOps(Renderer& renderer) {
+ std::vector<OffscreenBuffer*> temporaryLayers;
finishDefer();
/**
* Defines a LUT of lambdas which allow a recorded BakedOpState to use state->op->opId to
@@ -129,6 +130,7 @@ public:
} else if (!layer.empty()) {
// save layer - skip entire layer if empty (in which case, LayerOp has null layer).
layer.offscreenBuffer = renderer.startTemporaryLayer(layer.width, layer.height);
+ temporaryLayers.push_back(layer.offscreenBuffer);
GL_CHECKPOINT(MODERATE);
layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
GL_CHECKPOINT(MODERATE);
@@ -145,6 +147,10 @@ public:
GL_CHECKPOINT(MODERATE);
renderer.endFrame(fbo0.repaintRect);
}
+
+ for (auto& temporaryLayer : temporaryLayers) {
+ renderer.recycleTemporaryLayer(temporaryLayer);
+ }
}
void dump() const {
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
index 8f837f6048d6..0932d653fd5e 100644
--- a/libs/hwui/PropertyValuesHolder.cpp
+++ b/libs/hwui/PropertyValuesHolder.cpp
@@ -53,7 +53,7 @@ void GroupPropertyValuesHolder::setFraction(float fraction) {
} else {
animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
}
- mGroup->setPropertyValue(mPropertyId, animatedValue);
+ mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
}
inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
@@ -72,7 +72,7 @@ SkColor FullPathColorPropertyValuesHolder::interpolateColors(SkColor fromColor,
void FullPathColorPropertyValuesHolder::setFraction(float fraction) {
SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction);
- mFullPath->setColorPropertyValue(mPropertyId, animatedValue);
+ mFullPath->mutateProperties()->setColorPropertyValue(mPropertyId, animatedValue);
}
void FullPathPropertyValuesHolder::setFraction(float fraction) {
@@ -82,17 +82,17 @@ void FullPathPropertyValuesHolder::setFraction(float fraction) {
} else {
animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
}
- mFullPath->setPropertyValue(mPropertyId, animatedValue);
+ mFullPath->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
}
void PathDataPropertyValuesHolder::setFraction(float fraction) {
VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction);
- mPath->setPathData(mPathData);
+ mPath->mutateProperties()->setData(mPathData);
}
void RootAlphaPropertyValuesHolder::setFraction(float fraction) {
float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
- mTree->setRootAlpha(animatedValue);
+ mTree->mutateProperties()->setRootAlpha(animatedValue);
}
} // namepace uirenderer
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index 0271a80d4c17..aee9d6370083 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -501,22 +501,20 @@ struct CopyFromLayerOp : RecordedOp {
* when creating/tracking a SkPaint* during defer isn't worth the bother.
*/
struct LayerOp : RecordedOp {
- // Records a one-use (saveLayer) layer for drawing. Once drawn, the layer will be destroyed.
+ // Records a one-use (saveLayer) layer for drawing.
LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
: SUPER_PAINTLESS(LayerOp)
, layerHandle(layerHandle)
, alpha(paint ? paint->getAlpha() / 255.0f : 1.0f)
, mode(PaintUtils::getXfermodeDirect(paint))
- , colorFilter(paint ? paint->getColorFilter() : nullptr)
- , destroy(true) {}
+ , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
LayerOp(RenderNode& node)
: RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr)
, layerHandle(node.getLayerHandle())
, alpha(node.properties().layerProperties().alpha() / 255.0f)
, mode(node.properties().layerProperties().xferMode())
- , colorFilter(node.properties().layerProperties().colorFilter())
- , destroy(false) {}
+ , colorFilter(node.properties().layerProperties().colorFilter()) {}
// Records a handle to the Layer object, since the Layer itself won't be
// constructed until after this operation is constructed.
@@ -527,9 +525,6 @@ struct LayerOp : RecordedOp {
// pointer to object owned by either LayerProperties, or a recorded Paint object in a
// BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
SkColorFilter* colorFilter;
-
- // whether to destroy the layer, once rendered
- const bool destroy;
};
}; // namespace uirenderer
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 4f9cd688d4b6..b78497d6b6fc 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -430,10 +430,11 @@ void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
}
void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
+ mDisplayList->pushStagingFunctors.push_back(tree->getFunctor());
mDisplayList->ref(tree);
addOp(alloc().create_trivial<VectorDrawableOp>(
tree,
- Rect(tree->getBounds()),
+ Rect(tree->stagingProperties()->getBounds()),
*(mState.currentSnapshot()->transform),
getRecordedClip()));
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index f6f92f731c1c..957848628059 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -477,6 +477,9 @@ void RenderNode::syncDisplayList(TreeObserver* observer) {
for (size_t i = 0; i < mDisplayList->getFunctors().size(); i++) {
(*mDisplayList->getFunctors()[i])(DrawGlInfo::kModeSync, nullptr);
}
+ for (size_t i = 0; i < mDisplayList->getPushStagingFunctors().size(); i++) {
+ (*mDisplayList->getPushStagingFunctors()[i])();
+ }
}
}
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index f577785110d3..5ebf5458da18 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -155,6 +155,23 @@ void RenderProperties::debugOutputProperties(const int level) const {
ALOGD("%*s(ClipRect %d, %d, %d, %d)", level * 2, "",
(int)clipRect.left, (int)clipRect.top, (int)clipRect.right, (int)clipRect.bottom);
}
+
+ if (getRevealClip().willClip()) {
+ Rect bounds;
+ getRevealClip().getBounds(&bounds);
+ ALOGD("%*s(Clip to reveal clip with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
+ RECT_ARGS(bounds));
+ }
+
+ auto& outline = mPrimitiveFields.mOutline;
+ if (outline.getShouldClip()) {
+ if (outline.isEmpty()) {
+ ALOGD("%*s(Clip to empty outline)", level * 2, "");
+ } else if (outline.willClip()) {
+ ALOGD("%*s(Clip to outline with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
+ RECT_ARGS(outline.getBounds()));
+ }
+ }
}
void RenderProperties::updateMatrix() {
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 5d24fa009f04..1b459c142561 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -747,11 +747,7 @@ void SkiaCanvas::drawNinePatch(const SkBitmap& bitmap, const Res_png_9patch& chu
}
void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
- const SkBitmap& bitmap = vectorDrawable->getBitmapUpdateIfDirty();
- SkRect bounds = vectorDrawable->getBounds();
- drawBitmap(bitmap, 0, 0, bitmap.width(), bitmap.height(),
- bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
- vectorDrawable->getPaint());
+ vectorDrawable->drawStaging(this);
}
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index d35f76485bd1..adfe45c64885 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -17,6 +17,7 @@
#include "VectorDrawable.h"
#include "PathParser.h"
+#include "SkColorFilter.h"
#include "SkImageInfo.h"
#include "SkShader.h"
#include <utils/Log.h>
@@ -32,41 +33,36 @@ namespace VectorDrawable {
const int Tree::MAX_CACHED_BITMAP_SIZE = 2048;
-void Path::draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix, float scaleX, float scaleY) {
+void Path::draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix, float scaleX, float scaleY,
+ bool useStagingData) {
float matrixScale = getMatrixScale(groupStackedMatrix);
if (matrixScale == 0) {
// When either x or y is scaled to 0, we don't need to draw anything.
return;
}
- const SkPath updatedPath = getUpdatedPath();
SkMatrix pathMatrix(groupStackedMatrix);
pathMatrix.postScale(scaleX, scaleY);
//TODO: try apply the path matrix to the canvas instead of creating a new path.
SkPath renderPath;
renderPath.reset();
- renderPath.addPath(updatedPath, pathMatrix);
+
+ if (useStagingData) {
+ SkPath tmpPath;
+ getStagingPath(&tmpPath);
+ renderPath.addPath(tmpPath, pathMatrix);
+ } else {
+ renderPath.addPath(getUpdatedPath(), pathMatrix);
+ }
float minScale = fmin(scaleX, scaleY);
float strokeScale = minScale * matrixScale;
- drawPath(outCanvas, renderPath, strokeScale, pathMatrix);
-}
-
-void Path::setPathData(const Data& data) {
- if (mData == data) {
- return;
- }
- // Updates the path data. Note that we don't generate a new Skia path right away
- // because there are cases where the animation is changing the path data, but the view
- // that hosts the VD has gone off screen, in which case we won't even draw. So we
- // postpone the Skia path generation to the draw time.
- mData = data;
- mSkPathDirty = true;
+ drawPath(outCanvas, renderPath, strokeScale, pathMatrix, useStagingData);
}
void Path::dump() {
- ALOGD("Path: %s has %zu points", mName.c_str(), mData.points.size());
+ ALOGD("Path: %s has %zu points", mName.c_str(), mProperties.getData().points.size());
}
float Path::getMatrixScale(const SkMatrix& groupStackedMatrix) {
@@ -95,213 +91,215 @@ float Path::getMatrixScale(const SkMatrix& groupStackedMatrix) {
}
return matrixScale;
}
+
+// Called from UI thread during the initial setup/theme change.
Path::Path(const char* pathStr, size_t strLength) {
PathParser::ParseResult result;
- PathParser::getPathDataFromString(&mData, &result, pathStr, strLength);
- if (!result.failureOccurred) {
- VectorDrawableUtils::verbsToPath(&mSkPath, mData);
- }
-}
-
-Path::Path(const Data& data) {
- mData = data;
- // Now we need to construct a path
- VectorDrawableUtils::verbsToPath(&mSkPath, data);
+ Data data;
+ PathParser::getPathDataFromString(&data, &result, pathStr, strLength);
+ mStagingProperties.setData(data);
}
Path::Path(const Path& path) : Node(path) {
- mData = path.mData;
- VectorDrawableUtils::verbsToPath(&mSkPath, mData);
-}
-
-bool Path::canMorph(const Data& morphTo) {
- return VectorDrawableUtils::canMorph(mData, morphTo);
-}
-
-bool Path::canMorph(const Path& path) {
- return canMorph(path.mData);
+ mStagingProperties.syncProperties(path.mStagingProperties);
}
const SkPath& Path::getUpdatedPath() {
if (mSkPathDirty) {
mSkPath.reset();
- VectorDrawableUtils::verbsToPath(&mSkPath, mData);
+ VectorDrawableUtils::verbsToPath(&mSkPath, mProperties.getData());
mSkPathDirty = false;
}
return mSkPath;
}
-void Path::setPath(const char* pathStr, size_t strLength) {
- PathParser::ParseResult result;
- mSkPathDirty = true;
- PathParser::getPathDataFromString(&mData, &result, pathStr, strLength);
+void Path::getStagingPath(SkPath* outPath) {
+ outPath->reset();
+ VectorDrawableUtils::verbsToPath(outPath, mStagingProperties.getData());
+}
+
+void Path::syncProperties() {
+ if (mStagingPropertiesDirty) {
+ mProperties.syncProperties(mStagingProperties);
+ } else {
+ mStagingProperties.syncProperties(mProperties);
+ }
+ mStagingPropertiesDirty = false;
}
FullPath::FullPath(const FullPath& path) : Path(path) {
- mProperties = path.mProperties;
- SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient);
- SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient);
+ mStagingProperties.syncProperties(path.mStagingProperties);
+}
+
+static void applyTrim(SkPath* outPath, const SkPath& inPath, float trimPathStart, float trimPathEnd,
+ float trimPathOffset) {
+ if (trimPathStart == 0.0f && trimPathEnd == 1.0f) {
+ *outPath = inPath;
+ return;
+ }
+ outPath->reset();
+ if (trimPathStart == trimPathEnd) {
+ // Trimmed path should be empty.
+ return;
+ }
+ SkPathMeasure measure(inPath, false);
+ float len = SkScalarToFloat(measure.getLength());
+ float start = len * fmod((trimPathStart + trimPathOffset), 1.0f);
+ float end = len * fmod((trimPathEnd + trimPathOffset), 1.0f);
+
+ if (start > end) {
+ measure.getSegment(start, len, outPath, true);
+ if (end > 0) {
+ measure.getSegment(0, end, outPath, true);
+ }
+ } else {
+ measure.getSegment(start, end, outPath, true);
+ }
}
const SkPath& FullPath::getUpdatedPath() {
- if (!mSkPathDirty && !mTrimDirty) {
+ if (!mSkPathDirty && !mProperties.mTrimDirty) {
return mTrimmedSkPath;
}
Path::getUpdatedPath();
- if (mProperties.trimPathStart != 0.0f || mProperties.trimPathEnd != 1.0f) {
- applyTrim();
+ if (mProperties.getTrimPathStart() != 0.0f || mProperties.getTrimPathEnd() != 1.0f) {
+ mProperties.mTrimDirty = false;
+ applyTrim(&mTrimmedSkPath, mSkPath, mProperties.getTrimPathStart(),
+ mProperties.getTrimPathEnd(), mProperties.getTrimPathOffset());
return mTrimmedSkPath;
} else {
return mSkPath;
}
}
-void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
- SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
- float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
- int fillType) {
- mProperties.strokeWidth = strokeWidth;
- mProperties.strokeColor = strokeColor;
- mProperties.strokeAlpha = strokeAlpha;
- mProperties.fillColor = fillColor;
- mProperties.fillAlpha = fillAlpha;
- mProperties.strokeMiterLimit = strokeMiterLimit;
- mProperties.strokeLineCap = strokeLineCap;
- mProperties.strokeLineJoin = strokeLineJoin;
- mProperties.fillType = fillType;
+void FullPath::getStagingPath(SkPath* outPath) {
+ Path::getStagingPath(outPath);
+ SkPath inPath = *outPath;
+ applyTrim(outPath, inPath, mStagingProperties.getTrimPathStart(),
+ mStagingProperties.getTrimPathEnd(), mStagingProperties.getTrimPathOffset());
+}
- // If any trim property changes, mark trim dirty and update the trim path
- setTrimPathStart(trimPathStart);
- setTrimPathEnd(trimPathEnd);
- setTrimPathOffset(trimPathOffset);
+void FullPath::dump() {
+ Path::dump();
+ ALOGD("stroke width, color, alpha: %f, %d, %f, fill color, alpha: %d, %f",
+ mProperties.getStrokeWidth(), mProperties.getStrokeColor(), mProperties.getStrokeAlpha(),
+ mProperties.getFillColor(), mProperties.getFillAlpha());
}
+
inline SkColor applyAlpha(SkColor color, float alpha) {
int alphaBytes = SkColorGetA(color);
return SkColorSetA(color, alphaBytes * alpha);
}
void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale,
- const SkMatrix& matrix){
+ const SkMatrix& matrix, bool useStagingData){
+ const FullPathProperties& properties = useStagingData ? mStagingProperties : mProperties;
+
// Draw path's fill, if fill color or gradient is valid
bool needsFill = false;
- if (mFillGradient != nullptr) {
- mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.fillAlpha));
- SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix);
- mPaint.setShader(newShader);
+ SkPaint paint;
+ if (properties.getFillGradient() != nullptr) {
+ paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha()));
+ SkShader* newShader = properties.getFillGradient()->newWithLocalMatrix(matrix);
+ paint.setShader(newShader);
needsFill = true;
- } else if (mProperties.fillColor != SK_ColorTRANSPARENT) {
- mPaint.setColor(applyAlpha(mProperties.fillColor, mProperties.fillAlpha));
+ } else if (properties.getFillColor() != SK_ColorTRANSPARENT) {
+ paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha()));
needsFill = true;
}
if (needsFill) {
- mPaint.setStyle(SkPaint::Style::kFill_Style);
- mPaint.setAntiAlias(true);
- SkPath::FillType ft = static_cast<SkPath::FillType>(mProperties.fillType);
+ paint.setStyle(SkPaint::Style::kFill_Style);
+ paint.setAntiAlias(true);
+ SkPath::FillType ft = static_cast<SkPath::FillType>(properties.getFillType());
renderPath.setFillType(ft);
- outCanvas->drawPath(renderPath, mPaint);
+ outCanvas->drawPath(renderPath, paint);
}
- // Draw path's stroke, if stroke color or gradient is valid
+ // Draw path's stroke, if stroke color or Gradient is valid
bool needsStroke = false;
- if (mStrokeGradient != nullptr) {
- mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.strokeAlpha));
- SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix);
- mPaint.setShader(newShader);
+ if (properties.getStrokeGradient() != nullptr) {
+ paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha()));
+ SkShader* newShader = properties.getStrokeGradient()->newWithLocalMatrix(matrix);
+ paint.setShader(newShader);
needsStroke = true;
- } else if (mProperties.strokeColor != SK_ColorTRANSPARENT) {
- mPaint.setColor(applyAlpha(mProperties.strokeColor, mProperties.strokeAlpha));
+ } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) {
+ paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha()));
needsStroke = true;
}
if (needsStroke) {
- mPaint.setStyle(SkPaint::Style::kStroke_Style);
- mPaint.setAntiAlias(true);
- mPaint.setStrokeJoin(SkPaint::Join(mProperties.strokeLineJoin));
- mPaint.setStrokeCap(SkPaint::Cap(mProperties.strokeLineCap));
- mPaint.setStrokeMiter(mProperties.strokeMiterLimit);
- mPaint.setStrokeWidth(mProperties.strokeWidth * strokeScale);
- outCanvas->drawPath(renderPath, mPaint);
+ paint.setStyle(SkPaint::Style::kStroke_Style);
+ paint.setAntiAlias(true);
+ paint.setStrokeJoin(SkPaint::Join(properties.getStrokeLineJoin()));
+ paint.setStrokeCap(SkPaint::Cap(properties.getStrokeLineCap()));
+ paint.setStrokeMiter(properties.getStrokeMiterLimit());
+ paint.setStrokeWidth(properties.getStrokeWidth() * strokeScale);
+ outCanvas->drawPath(renderPath, paint);
}
}
-/**
- * Applies trimming to the specified path.
- */
-void FullPath::applyTrim() {
- if (mProperties.trimPathStart == 0.0f && mProperties.trimPathEnd == 1.0f) {
- // No trimming necessary.
- return;
- }
- mTrimDirty = false;
- mTrimmedSkPath.reset();
- if (mProperties.trimPathStart == mProperties.trimPathEnd) {
- // Trimmed path should be empty.
- return;
- }
- SkPathMeasure measure(mSkPath, false);
- float len = SkScalarToFloat(measure.getLength());
- float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f);
- float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f);
+void FullPath::syncProperties() {
+ Path::syncProperties();
- if (start > end) {
- measure.getSegment(start, len, &mTrimmedSkPath, true);
- if (end > 0) {
- measure.getSegment(0, end, &mTrimmedSkPath, true);
- }
+ if (mStagingPropertiesDirty) {
+ mProperties.syncProperties(mStagingProperties);
} else {
- measure.getSegment(start, end, &mTrimmedSkPath, true);
+ // Update staging property with property values from animation.
+ mStagingProperties.syncProperties(mProperties);
}
+ mStagingPropertiesDirty = false;
}
-REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties);
+REQUIRE_COMPATIBLE_LAYOUT(FullPath::FullPathProperties::PrimitiveFields);
static_assert(sizeof(float) == sizeof(int32_t), "float is not the same size as int32_t");
static_assert(sizeof(SkColor) == sizeof(int32_t), "SkColor is not the same size as int32_t");
-bool FullPath::getProperties(int8_t* outProperties, int length) {
- int propertyDataSize = sizeof(Properties);
+bool FullPath::FullPathProperties::copyProperties(int8_t* outProperties, int length) const {
+ int propertyDataSize = sizeof(FullPathProperties::PrimitiveFields);
if (length != propertyDataSize) {
LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
propertyDataSize, length);
return false;
}
- Properties* out = reinterpret_cast<Properties*>(outProperties);
- *out = mProperties;
+
+ PrimitiveFields* out = reinterpret_cast<PrimitiveFields*>(outProperties);
+ *out = mPrimitiveFields;
return true;
}
-void FullPath::setColorPropertyValue(int propertyId, int32_t value) {
+void FullPath::FullPathProperties::setColorPropertyValue(int propertyId, int32_t value) {
Property currentProperty = static_cast<Property>(propertyId);
- if (currentProperty == Property::StrokeColor) {
- mProperties.strokeColor = value;
- } else if (currentProperty == Property::FillColor) {
- mProperties.fillColor = value;
+ if (currentProperty == Property::strokeColor) {
+ setStrokeColor(value);
+ } else if (currentProperty == Property::fillColor) {
+ setFillColor(value);
} else {
- LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property with id: %d",
- propertyId);
+ LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property"
+ " with id: %d", propertyId);
}
}
-void FullPath::setPropertyValue(int propertyId, float value) {
+void FullPath::FullPathProperties::setPropertyValue(int propertyId, float value) {
Property property = static_cast<Property>(propertyId);
switch (property) {
- case Property::StrokeWidth:
+ case Property::strokeWidth:
setStrokeWidth(value);
break;
- case Property::StrokeAlpha:
+ case Property::strokeAlpha:
setStrokeAlpha(value);
break;
- case Property::FillAlpha:
+ case Property::fillAlpha:
setFillAlpha(value);
break;
- case Property::TrimPathStart:
+ case Property::trimPathStart:
setTrimPathStart(value);
break;
- case Property::TrimPathEnd:
+ case Property::trimPathEnd:
setTrimPathEnd(value);
break;
- case Property::TrimPathOffset:
+ case Property::trimPathOffset:
setTrimPathOffset(value);
break;
default:
@@ -311,16 +309,16 @@ void FullPath::setPropertyValue(int propertyId, float value) {
}
void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
- float strokeScale, const SkMatrix& matrix){
+ float strokeScale, const SkMatrix& matrix, bool useStagingData){
outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
}
Group::Group(const Group& group) : Node(group) {
- mProperties = group.mProperties;
+ mStagingProperties.syncProperties(group.mStagingProperties);
}
void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scaleX,
- float scaleY) {
+ float scaleY, bool useStagingData) {
// TODO: Try apply the matrix to the canvas instead of passing it down the tree
// Calculate current group's matrix by preConcat the parent's and
@@ -328,14 +326,15 @@ void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scale
// Basically the Mfinal = Mviewport * M0 * M1 * M2;
// Mi the local matrix at level i of the group tree.
SkMatrix stackedMatrix;
- getLocalMatrix(&stackedMatrix);
+ const GroupProperties& prop = useStagingData ? mStagingProperties : mProperties;
+ getLocalMatrix(&stackedMatrix, prop);
stackedMatrix.postConcat(currentMatrix);
// Save the current clip information, which is local to this group.
outCanvas->save();
// Draw the group tree in the same order as the XML file.
for (auto& child : mChildren) {
- child->draw(outCanvas, stackedMatrix, scaleX, scaleY);
+ child->draw(outCanvas, stackedMatrix, scaleX, scaleY, useStagingData);
}
// Restore the previous clip information.
outCanvas->restore();
@@ -343,96 +342,106 @@ void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scale
void Group::dump() {
ALOGD("Group %s has %zu children: ", mName.c_str(), mChildren.size());
+ ALOGD("Group translateX, Y : %f, %f, scaleX, Y: %f, %f", mProperties.getTranslateX(),
+ mProperties.getTranslateY(), mProperties.getScaleX(), mProperties.getScaleY());
for (size_t i = 0; i < mChildren.size(); i++) {
mChildren[i]->dump();
}
}
-void Group::updateLocalMatrix(float rotate, float pivotX, float pivotY,
- float scaleX, float scaleY, float translateX, float translateY) {
- setRotation(rotate);
- setPivotX(pivotX);
- setPivotY(pivotY);
- setScaleX(scaleX);
- setScaleY(scaleY);
- setTranslateX(translateX);
- setTranslateY(translateY);
+void Group::syncProperties() {
+ // Copy over the dirty staging properties
+ if (mStagingPropertiesDirty) {
+ mProperties.syncProperties(mStagingProperties);
+ } else {
+ mStagingProperties.syncProperties(mProperties);
+ }
+ mStagingPropertiesDirty = false;
+ for (auto& child : mChildren) {
+ child->syncProperties();
+ }
}
-void Group::getLocalMatrix(SkMatrix* outMatrix) {
+void Group::getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties) {
outMatrix->reset();
// TODO: use rotate(mRotate, mPivotX, mPivotY) and scale with pivot point, instead of
// translating to pivot for rotating and scaling, then translating back.
- outMatrix->postTranslate(-mProperties.pivotX, -mProperties.pivotY);
- outMatrix->postScale(mProperties.scaleX, mProperties.scaleY);
- outMatrix->postRotate(mProperties.rotate, 0, 0);
- outMatrix->postTranslate(mProperties.translateX + mProperties.pivotX,
- mProperties.translateY + mProperties.pivotY);
+ outMatrix->postTranslate(-properties.getPivotX(), -properties.getPivotY());
+ outMatrix->postScale(properties.getScaleX(), properties.getScaleY());
+ outMatrix->postRotate(properties.getRotation(), 0, 0);
+ outMatrix->postTranslate(properties.getTranslateX() + properties.getPivotX(),
+ properties.getTranslateY() + properties.getPivotY());
}
void Group::addChild(Node* child) {
mChildren.emplace_back(child);
+ if (mPropertyChangedListener != nullptr) {
+ child->setPropertyChangedListener(mPropertyChangedListener);
+ }
}
-bool Group::getProperties(float* outProperties, int length) {
- int propertyCount = static_cast<int>(Property::Count);
+bool Group::GroupProperties::copyProperties(float* outProperties, int length) const {
+ int propertyCount = static_cast<int>(Property::count);
if (length != propertyCount) {
LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
propertyCount, length);
return false;
}
- Properties* out = reinterpret_cast<Properties*>(outProperties);
- *out = mProperties;
+
+ PrimitiveFields* out = reinterpret_cast<PrimitiveFields*>(outProperties);
+ *out = mPrimitiveFields;
return true;
}
// TODO: Consider animating the properties as float pointers
-float Group::getPropertyValue(int propertyId) const {
+// Called on render thread
+float Group::GroupProperties::getPropertyValue(int propertyId) const {
Property currentProperty = static_cast<Property>(propertyId);
switch (currentProperty) {
- case Property::Rotate:
- return mProperties.rotate;
- case Property::PivotX:
- return mProperties.pivotX;
- case Property::PivotY:
- return mProperties.pivotY;
- case Property::ScaleX:
- return mProperties.scaleX;
- case Property::ScaleY:
- return mProperties.scaleY;
- case Property::TranslateX:
- return mProperties.translateX;
- case Property::TranslateY:
- return mProperties.translateY;
+ case Property::rotate:
+ return getRotation();
+ case Property::pivotX:
+ return getPivotX();
+ case Property::pivotY:
+ return getPivotY();
+ case Property::scaleX:
+ return getScaleX();
+ case Property::scaleY:
+ return getScaleY();
+ case Property::translateX:
+ return getTranslateX();
+ case Property::translateY:
+ return getTranslateY();
default:
LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
return 0;
}
}
-void Group::setPropertyValue(int propertyId, float value) {
+// Called on render thread
+void Group::GroupProperties::setPropertyValue(int propertyId, float value) {
Property currentProperty = static_cast<Property>(propertyId);
switch (currentProperty) {
- case Property::Rotate:
- mProperties.rotate = value;
+ case Property::rotate:
+ setRotation(value);
break;
- case Property::PivotX:
- mProperties.pivotX = value;
+ case Property::pivotX:
+ setPivotX(value);
break;
- case Property::PivotY:
- mProperties.pivotY = value;
+ case Property::pivotY:
+ setPivotY(value);
break;
- case Property::ScaleX:
- mProperties.scaleX = value;
+ case Property::scaleX:
+ setScaleX(value);
break;
- case Property::ScaleY:
- mProperties.scaleY = value;
+ case Property::scaleY:
+ setScaleY(value);
break;
- case Property::TranslateX:
- mProperties.translateX = value;
+ case Property::translateX:
+ setTranslateX(value);
break;
- case Property::TranslateY:
- mProperties.translateY = value;
+ case Property::translateY:
+ setTranslateY(value);
break;
default:
LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
@@ -440,7 +449,11 @@ void Group::setPropertyValue(int propertyId, float value) {
}
bool Group::isValidProperty(int propertyId) {
- return propertyId >= 0 && propertyId < static_cast<int>(Property::Count);
+ return GroupProperties::isValidProperty(propertyId);
+}
+
+bool Group::GroupProperties::isValidProperty(int propertyId) {
+ return propertyId >= 0 && propertyId < static_cast<int>(Property::count);
}
void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
@@ -449,18 +462,18 @@ void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
// avoid blurry scaling, we have to draw into a bitmap with exact pixel
// size first. This bitmap size is determined by the bounds and the
// canvas scale.
- outCanvas->getMatrix(&mCanvasMatrix);
- mBounds = bounds;
+ SkMatrix canvasMatrix;
+ outCanvas->getMatrix(&canvasMatrix);
float canvasScaleX = 1.0f;
float canvasScaleY = 1.0f;
- if (mCanvasMatrix.getSkewX() == 0 && mCanvasMatrix.getSkewY() == 0) {
+ if (canvasMatrix.getSkewX() == 0 && canvasMatrix.getSkewY() == 0) {
// Only use the scale value when there's no skew or rotation in the canvas matrix.
// TODO: Add a cts test for drawing VD on a canvas with negative scaling factors.
- canvasScaleX = fabs(mCanvasMatrix.getScaleX());
- canvasScaleY = fabs(mCanvasMatrix.getScaleY());
+ canvasScaleX = fabs(canvasMatrix.getScaleX());
+ canvasScaleY = fabs(canvasMatrix.getScaleY());
}
- int scaledWidth = (int) (mBounds.width() * canvasScaleX);
- int scaledHeight = (int) (mBounds.height() * canvasScaleY);
+ int scaledWidth = (int) (bounds.width() * canvasScaleX);
+ int scaledHeight = (int) (bounds.height() * canvasScaleY);
scaledWidth = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledWidth);
scaledHeight = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledHeight);
@@ -468,63 +481,105 @@ void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
return;
}
- mPaint.setColorFilter(colorFilter);
-
+ mStagingProperties.setScaledSize(scaledWidth, scaledHeight);
int saveCount = outCanvas->save(SaveFlags::MatrixClip);
- outCanvas->translate(mBounds.fLeft, mBounds.fTop);
+ outCanvas->translate(bounds.fLeft, bounds.fTop);
// Handle RTL mirroring.
if (needsMirroring) {
- outCanvas->translate(mBounds.width(), 0);
+ outCanvas->translate(bounds.width(), 0);
outCanvas->scale(-1.0f, 1.0f);
}
+ mStagingProperties.setColorFilter(colorFilter);
// At this point, canvas has been translated to the right position.
// And we use this bound for the destination rect for the drawBitmap, so
// we offset to (0, 0);
- mBounds.offsetTo(0, 0);
- createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
-
+ SkRect tmpBounds = bounds;
+ tmpBounds.offsetTo(0, 0);
+ mStagingProperties.setBounds(tmpBounds);
outCanvas->drawVectorDrawable(this);
-
outCanvas->restoreToCount(saveCount);
}
+void Tree::drawStaging(Canvas* outCanvas) {
+ bool redrawNeeded = allocateBitmapIfNeeded(&mStagingCache.bitmap,
+ mStagingProperties.getScaledWidth(), mStagingProperties.getScaledHeight());
+ // draw bitmap cache
+ if (redrawNeeded || mStagingCache.dirty) {
+ updateBitmapCache(&mStagingCache.bitmap, true);
+ mStagingCache.dirty = false;
+ }
+
+ SkPaint tmpPaint;
+ SkPaint* paint = updatePaint(&tmpPaint, &mStagingProperties);
+ outCanvas->drawBitmap(mStagingCache.bitmap, 0, 0,
+ mStagingCache.bitmap.width(), mStagingCache.bitmap.height(),
+ mStagingProperties.getBounds().left(), mStagingProperties.getBounds().top(),
+ mStagingProperties.getBounds().right(), mStagingProperties.getBounds().bottom(), paint);
+}
+
SkPaint* Tree::getPaint() {
- SkPaint* paint;
- if (mRootAlpha == 1.0f && mPaint.getColorFilter() == NULL) {
- paint = NULL;
+ return updatePaint(&mPaint, &mProperties);
+}
+
+// Update the given paint with alpha and color filter. Return nullptr if no color filter is
+// specified and root alpha is 1. Otherwise, return updated paint.
+SkPaint* Tree::updatePaint(SkPaint* outPaint, TreeProperties* prop) {
+ if (prop->getRootAlpha() == 1.0f && prop->getColorFilter() == nullptr) {
+ return nullptr;
} else {
- mPaint.setFilterQuality(kLow_SkFilterQuality);
- mPaint.setAlpha(mRootAlpha * 255);
- paint = &mPaint;
+ outPaint->setColorFilter(mStagingProperties.getColorFilter());
+ outPaint->setFilterQuality(kLow_SkFilterQuality);
+ outPaint->setAlpha(prop->getRootAlpha() * 255);
+ return outPaint;
}
- return paint;
}
const SkBitmap& Tree::getBitmapUpdateIfDirty() {
- mCachedBitmap.eraseColor(SK_ColorTRANSPARENT);
- SkCanvas outCanvas(mCachedBitmap);
- float scaleX = (float) mCachedBitmap.width() / mViewportWidth;
- float scaleY = (float) mCachedBitmap.height() / mViewportHeight;
- mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY);
- mCacheDirty = false;
- return mCachedBitmap;
+ bool redrawNeeded = allocateBitmapIfNeeded(&mCache.bitmap, mProperties.getScaledWidth(),
+ mProperties.getScaledHeight());
+ if (redrawNeeded || mCache.dirty) {
+ updateBitmapCache(&mCache.bitmap, false);
+ mCache.dirty = false;
+ }
+ return mCache.bitmap;
+}
+
+void Tree::updateBitmapCache(SkBitmap* outCache, bool useStagingData) {
+ outCache->eraseColor(SK_ColorTRANSPARENT);
+ SkCanvas outCanvas(*outCache);
+ float viewportWidth = useStagingData ?
+ mStagingProperties.getViewportWidth() : mProperties.getViewportWidth();
+ float viewportHeight = useStagingData ?
+ mStagingProperties.getViewportHeight() : mProperties.getViewportHeight();
+ float scaleX = outCache->width() / viewportWidth;
+ float scaleY = outCache->height() / viewportHeight;
+ mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY, useStagingData);
}
-void Tree::createCachedBitmapIfNeeded(int width, int height) {
- if (!canReuseBitmap(width, height)) {
+bool Tree::allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height) {
+ if (!canReuseBitmap(*outCache, width, height)) {
SkImageInfo info = SkImageInfo::Make(width, height,
kN32_SkColorType, kPremul_SkAlphaType);
- mCachedBitmap.setInfo(info);
+ outCache->setInfo(info);
// TODO: Count the bitmap cache against app's java heap
- mCachedBitmap.allocPixels(info);
- mCacheDirty = true;
+ outCache->allocPixels(info);
+ return true;
}
+ return false;
}
-bool Tree::canReuseBitmap(int width, int height) {
- return width == mCachedBitmap.width() && height == mCachedBitmap.height();
+bool Tree::canReuseBitmap(const SkBitmap& bitmap, int width, int height) {
+ return width == bitmap.width() && height == bitmap.height();
+}
+
+void Tree::onPropertyChanged(TreeProperties* prop) {
+ if (prop == &mStagingProperties) {
+ mStagingCache.dirty = true;
+ } else {
+ mCache.dirty = true;
+ }
}
}; // namespace VectorDrawable
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 7a45bf5ca8a8..e4c7ed71f361 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -18,9 +18,11 @@
#define ANDROID_HWUI_VPATH_H
#include "hwui/Canvas.h"
+#include "DisplayList.h"
#include <SkBitmap.h>
#include <SkColor.h>
+#include <SkColorFilter.h>
#include <SkCanvas.h>
#include <SkMatrix.h>
#include <SkPaint.h>
@@ -38,8 +40,11 @@ namespace android {
namespace uirenderer {
namespace VectorDrawable {
-#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP(field, value) ? (flag = true, true): false);
+#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP_AND_NOTIFY(field, value) ? (flag = true, true) : false)
#define VD_SET_PROP(field, value) (value != field ? (field = value, true) : false)
+#define VD_SET_PROP_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP(field, value);\
+ onPropertyChanged(); retVal;})
+#define UPDATE_SKPROP(field, value) ({bool retVal = (field != value); if (field != value) SkRefCnt_SafeAssign(field, value); retVal;})
/* A VectorDrawable is composed of a tree of nodes.
* Each node can be a group node, or a path.
@@ -52,22 +57,65 @@ namespace VectorDrawable {
* / \ |
* Path Path Path
*
+ * VectorDrawables are drawn into bitmap caches first, then the caches are drawn to the given
+ * canvas with root alpha applied. Two caches are maintained for VD, one in UI thread, the other in
+ * Render Thread. A generation id is used to keep track of changes in the vector drawable tree.
+ * Each cache has their own generation id to track whether they are up to date with the latest
+ * change in the tree.
+ *
+ * Any property change to the vector drawable coming from UI thread (such as bulk setters to update
+ * all the properties, and viewport change, etc.) are only modifying the staging properties. The
+ * staging properties will then be marked dirty and will be pushed over to render thread properties
+ * at sync point. If staging properties are not dirty at sync point, we sync backwards by updating
+ * staging properties with render thread properties to reflect the latest animation value.
+ *
*/
+
+class PropertyChangedListener {
+public:
+ PropertyChangedListener(bool* dirty, bool* stagingDirty)
+ : mDirty(dirty), mStagingDirty(stagingDirty) {}
+ void onPropertyChanged() {
+ *mDirty = true;
+ }
+ void onStagingPropertyChanged() {
+ *mStagingDirty = true;
+ }
+private:
+ bool* mDirty;
+ bool* mStagingDirty;
+};
+
class ANDROID_API Node {
public:
+ class Properties {
+ public:
+ Properties(Node* node) : mNode(node) {}
+ inline void onPropertyChanged() {
+ mNode->onPropertyChanged(this);
+ }
+ private:
+ Node* mNode;
+ };
Node(const Node& node) {
mName = node.mName;
}
Node() {}
virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
- float scaleX, float scaleY) = 0;
+ float scaleX, float scaleY, bool useStagingData) = 0;
virtual void dump() = 0;
void setName(const char* name) {
mName = name;
}
+ virtual void setPropertyChangedListener(PropertyChangedListener* listener) {
+ mPropertyChangedListener = listener;
+ }
+ virtual void onPropertyChanged(Properties* properties) = 0;
virtual ~Node(){}
+ virtual void syncProperties() = 0;
protected:
std::string mName;
+ PropertyChangedListener* mPropertyChangedListener = nullptr;
};
class ANDROID_API Path : public Node {
@@ -81,150 +129,267 @@ public:
&& points == data.points;
}
};
- Path(const Data& nodes);
+
+ class PathProperties : public Properties {
+ public:
+ PathProperties(Node* node) : Properties(node) {}
+ void syncProperties(const PathProperties& prop) {
+ mData = prop.mData;
+ onPropertyChanged();
+ }
+ void setData(const Data& data) {
+ // Updates the path data. Note that we don't generate a new Skia path right away
+ // because there are cases where the animation is changing the path data, but the view
+ // that hosts the VD has gone off screen, in which case we won't even draw. So we
+ // postpone the Skia path generation to the draw time.
+ if (data == mData) {
+ return;
+ }
+ mData = data;
+ onPropertyChanged();
+
+ }
+ const Data& getData() const {
+ return mData;
+ }
+ private:
+ Data mData;
+ };
+
Path(const Path& path);
Path(const char* path, size_t strLength);
Path() {}
+
void dump() override;
- bool canMorph(const Data& path);
- bool canMorph(const Path& path);
void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix,
- float scaleX, float scaleY) override;
- void setPath(const char* path, size_t strLength);
- void setPathData(const Data& data);
+ float scaleX, float scaleY, bool useStagingData) override;
static float getMatrixScale(const SkMatrix& groupStackedMatrix);
+ virtual void syncProperties() override;
+ virtual void onPropertyChanged(Properties* prop) override {
+ if (prop == &mStagingProperties) {
+ mStagingPropertiesDirty = true;
+ if (mPropertyChangedListener) {
+ mPropertyChangedListener->onStagingPropertyChanged();
+ }
+ } else if (prop == &mProperties){
+ mSkPathDirty = true;
+ if (mPropertyChangedListener) {
+ mPropertyChangedListener->onPropertyChanged();
+ }
+ }
+ }
+ PathProperties* mutateStagingProperties() { return &mStagingProperties; }
+ const PathProperties* stagingProperties() { return &mStagingProperties; }
+
+ // This should only be called from animations on RT
+ PathProperties* mutateProperties() { return &mProperties; }
protected:
virtual const SkPath& getUpdatedPath();
+ virtual void getStagingPath(SkPath* outPath);
virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
- float strokeScale, const SkMatrix& matrix) = 0;
- Data mData;
- SkPath mSkPath;
+ float strokeScale, const SkMatrix& matrix, bool useStagingData) = 0;
+
+ // Internal data, render thread only.
bool mSkPathDirty = true;
+ SkPath mSkPath;
+
+private:
+ PathProperties mProperties = PathProperties(this);
+ PathProperties mStagingProperties = PathProperties(this);
+ bool mStagingPropertiesDirty = true;
};
class ANDROID_API FullPath: public Path {
public:
+ class FullPathProperties : public Properties {
+ public:
+ struct PrimitiveFields {
+ float strokeWidth = 0;
+ SkColor strokeColor = SK_ColorTRANSPARENT;
+ float strokeAlpha = 1;
+ SkColor fillColor = SK_ColorTRANSPARENT;
+ float fillAlpha = 1;
+ float trimPathStart = 0;
+ float trimPathEnd = 1;
+ float trimPathOffset = 0;
+ int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
+ int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
+ float strokeMiterLimit = 4;
+ int fillType = 0; /* non-zero or kWinding_FillType in Skia */
+ };
+ FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
+ void syncProperties(const FullPathProperties& prop) {
+ mPrimitiveFields = prop.mPrimitiveFields;
+ mTrimDirty = true;
+ fillGradient.reset(prop.fillGradient);
+ strokeGradient.reset(prop.strokeGradient);
+ onPropertyChanged();
+ }
+ void setFillGradient(SkShader* gradient) {
+ if(fillGradient != gradient){
+ fillGradient.reset(gradient);
+ onPropertyChanged();
+ }
+ }
+ void setStrokeGradient(SkShader* gradient) {
+ if(strokeGradient != gradient){
+ strokeGradient.reset(gradient);
+ onPropertyChanged();
+ }
+ }
+ SkShader* getFillGradient() const {
+ return fillGradient;
+ }
+ SkShader* getStrokeGradient() const {
+ return strokeGradient;
+ }
+ float getStrokeWidth() const{
+ return mPrimitiveFields.strokeWidth;
+ }
+ void setStrokeWidth(float strokeWidth) {
+ VD_SET_PROP_AND_NOTIFY(strokeWidth, strokeWidth);
+ }
+ SkColor getStrokeColor() const{
+ return mPrimitiveFields.strokeColor;
+ }
+ void setStrokeColor(SkColor strokeColor) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeColor, strokeColor);
+ }
+ float getStrokeAlpha() const{
+ return mPrimitiveFields.strokeAlpha;
+ }
+ void setStrokeAlpha(float strokeAlpha) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeAlpha, strokeAlpha);
+ }
+ SkColor getFillColor() const {
+ return mPrimitiveFields.fillColor;
+ }
+ void setFillColor(SkColor fillColor) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillColor, fillColor);
+ }
+ float getFillAlpha() const{
+ return mPrimitiveFields.fillAlpha;
+ }
+ void setFillAlpha(float fillAlpha) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillAlpha, fillAlpha);
+ }
+ float getTrimPathStart() const{
+ return mPrimitiveFields.trimPathStart;
+ }
+ void setTrimPathStart(float trimPathStart) {
+ VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathStart, trimPathStart, mTrimDirty);
+ }
+ float getTrimPathEnd() const{
+ return mPrimitiveFields.trimPathEnd;
+ }
+ void setTrimPathEnd(float trimPathEnd) {
+ VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathEnd, trimPathEnd, mTrimDirty);
+ }
+ float getTrimPathOffset() const{
+ return mPrimitiveFields.trimPathOffset;
+ }
+ void setTrimPathOffset(float trimPathOffset) {
+ VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathOffset, trimPathOffset, mTrimDirty);
+ }
-struct Properties {
- float strokeWidth = 0;
- SkColor strokeColor = SK_ColorTRANSPARENT;
- float strokeAlpha = 1;
- SkColor fillColor = SK_ColorTRANSPARENT;
- float fillAlpha = 1;
- float trimPathStart = 0;
- float trimPathEnd = 1;
- float trimPathOffset = 0;
- int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
- int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
- float strokeMiterLimit = 4;
- int fillType = 0; /* non-zero or kWinding_FillType in Skia */
-};
+ float getStrokeMiterLimit() const {
+ return mPrimitiveFields.strokeMiterLimit;
+ }
+ float getStrokeLineCap() const {
+ return mPrimitiveFields.strokeLineCap;
+ }
+ float getStrokeLineJoin() const {
+ return mPrimitiveFields.strokeLineJoin;
+ }
+ float getFillType() const {
+ return mPrimitiveFields.fillType;
+ }
+ bool copyProperties(int8_t* outProperties, int length) const;
+ void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
+ SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
+ float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
+ int fillType) {
+ mPrimitiveFields.strokeWidth = strokeWidth;
+ mPrimitiveFields.strokeColor = strokeColor;
+ mPrimitiveFields.strokeAlpha = strokeAlpha;
+ mPrimitiveFields.fillColor = fillColor;
+ mPrimitiveFields.fillAlpha = fillAlpha;
+ mPrimitiveFields.trimPathStart = trimPathStart;
+ mPrimitiveFields.trimPathEnd = trimPathEnd;
+ mPrimitiveFields.trimPathOffset = trimPathOffset;
+ mPrimitiveFields.strokeMiterLimit = strokeMiterLimit;
+ mPrimitiveFields.strokeLineCap = strokeLineCap;
+ mPrimitiveFields.strokeLineJoin = strokeLineJoin;
+ mPrimitiveFields.fillType = fillType;
+ mTrimDirty = true;
+ onPropertyChanged();
+ }
+ // Set property values during animation
+ void setColorPropertyValue(int propertyId, int32_t value);
+ void setPropertyValue(int propertyId, float value);
+ bool mTrimDirty;
+ private:
+ enum class Property {
+ strokeWidth = 0,
+ strokeColor,
+ strokeAlpha,
+ fillColor,
+ fillAlpha,
+ trimPathStart,
+ trimPathEnd,
+ trimPathOffset,
+ strokeLineCap,
+ strokeLineJoin,
+ strokeMiterLimit,
+ fillType,
+ count,
+ };
+ PrimitiveFields mPrimitiveFields;
+ SkAutoTUnref<SkShader> fillGradient;
+ SkAutoTUnref<SkShader> strokeGradient;
+ };
+ // Called from UI thread
FullPath(const FullPath& path); // for cloning
FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
FullPath() : Path() {}
- FullPath(const Data& nodes) : Path(nodes) {}
-
- ~FullPath() {
- SkSafeUnref(mFillGradient);
- SkSafeUnref(mStrokeGradient);
- }
-
- void updateProperties(float strokeWidth, SkColor strokeColor,
- float strokeAlpha, SkColor fillColor, float fillAlpha,
- float trimPathStart, float trimPathEnd, float trimPathOffset,
- float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType);
- // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
- float getStrokeWidth() {
- return mProperties.strokeWidth;
- }
- void setStrokeWidth(float strokeWidth) {
- mProperties.strokeWidth = strokeWidth;
- }
- SkColor getStrokeColor() {
- return mProperties.strokeColor;
- }
- void setStrokeColor(SkColor strokeColor) {
- mProperties.strokeColor = strokeColor;
- }
- float getStrokeAlpha() {
- return mProperties.strokeAlpha;
- }
- void setStrokeAlpha(float strokeAlpha) {
- mProperties.strokeAlpha = strokeAlpha;
- }
- SkColor getFillColor() {
- return mProperties.fillColor;
- }
- void setFillColor(SkColor fillColor) {
- mProperties.fillColor = fillColor;
- }
- float getFillAlpha() {
- return mProperties.fillAlpha;
- }
- void setFillAlpha(float fillAlpha) {
- mProperties.fillAlpha = fillAlpha;
- }
- float getTrimPathStart() {
- return mProperties.trimPathStart;
- }
- void setTrimPathStart(float trimPathStart) {
- VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty);
- }
- float getTrimPathEnd() {
- return mProperties.trimPathEnd;
- }
- void setTrimPathEnd(float trimPathEnd) {
- VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty);
- }
- float getTrimPathOffset() {
- return mProperties.trimPathOffset;
- }
- void setTrimPathOffset(float trimPathOffset) {
- VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty);
+ void dump() override;
+ FullPathProperties* mutateStagingProperties() { return &mStagingProperties; }
+ const FullPathProperties* stagingProperties() { return &mStagingProperties; }
+
+ // This should only be called from animations on RT
+ FullPathProperties* mutateProperties() { return &mProperties; }
+
+ virtual void syncProperties() override;
+ virtual void onPropertyChanged(Properties* properties) override {
+ Path::onPropertyChanged(properties);
+ if (properties == &mStagingProperties) {
+ mStagingPropertiesDirty = true;
+ if (mPropertyChangedListener) {
+ mPropertyChangedListener->onStagingPropertyChanged();
+ }
+ } else if (properties == &mProperties) {
+ if (mPropertyChangedListener) {
+ mPropertyChangedListener->onPropertyChanged();
+ }
+ }
}
- bool getProperties(int8_t* outProperties, int length);
- void setColorPropertyValue(int propertyId, int32_t value);
- void setPropertyValue(int propertyId, float value);
-
- void setFillGradient(SkShader* fillGradient) {
- SkRefCnt_SafeAssign(mFillGradient, fillGradient);
- };
- void setStrokeGradient(SkShader* strokeGradient) {
- SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient);
- };
-
protected:
const SkPath& getUpdatedPath() override;
+ void getStagingPath(SkPath* outPath) override;
void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
- float strokeScale, const SkMatrix& matrix) override;
-
+ float strokeScale, const SkMatrix& matrix, bool useStagingData) override;
private:
- enum class Property {
- StrokeWidth = 0,
- StrokeColor,
- StrokeAlpha,
- FillColor,
- FillAlpha,
- TrimPathStart,
- TrimPathEnd,
- TrimPathOffset,
- StrokeLineCap,
- StrokeLineJoin,
- StrokeMiterLimit,
- FillType,
- Count,
- };
- // Applies trimming to the specified path.
- void applyTrim();
- Properties mProperties;
- bool mTrimDirty = true;
+
+ FullPathProperties mProperties = FullPathProperties(this);
+ FullPathProperties mStagingProperties = FullPathProperties(this);
+ bool mStagingPropertiesDirty = true;
+
+ // Intermediate data for drawing, render thread only
SkPath mTrimmedSkPath;
- SkPaint mPaint;
- SkShader* mStrokeGradient = nullptr;
- SkShader* mFillGradient = nullptr;
+
};
class ANDROID_API ClipPath: public Path {
@@ -232,143 +397,316 @@ public:
ClipPath(const ClipPath& path) : Path(path) {}
ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
ClipPath() : Path() {}
- ClipPath(const Data& nodes) : Path(nodes) {}
protected:
void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
- float strokeScale, const SkMatrix& matrix) override;
+ float strokeScale, const SkMatrix& matrix, bool useStagingData) override;
};
class ANDROID_API Group: public Node {
public:
- struct Properties {
- float rotate = 0;
- float pivotX = 0;
- float pivotY = 0;
- float scaleX = 1;
- float scaleY = 1;
- float translateX = 0;
- float translateY = 0;
+ class GroupProperties : public Properties {
+ public:
+ GroupProperties(Node* mNode) : Properties(mNode) {}
+ struct PrimitiveFields {
+ float rotate = 0;
+ float pivotX = 0;
+ float pivotY = 0;
+ float scaleX = 1;
+ float scaleY = 1;
+ float translateX = 0;
+ float translateY = 0;
+ } mPrimitiveFields;
+ void syncProperties(const GroupProperties& prop) {
+ mPrimitiveFields = prop.mPrimitiveFields;
+ onPropertyChanged();
+ }
+ float getRotation() const {
+ return mPrimitiveFields.rotate;
+ }
+ void setRotation(float rotation) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.rotate, rotation);
+ }
+ float getPivotX() const {
+ return mPrimitiveFields.pivotX;
+ }
+ void setPivotX(float pivotX) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotX, pivotX);
+ }
+ float getPivotY() const {
+ return mPrimitiveFields.pivotY;
+ }
+ void setPivotY(float pivotY) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotY, pivotY);
+ }
+ float getScaleX() const {
+ return mPrimitiveFields.scaleX;
+ }
+ void setScaleX(float scaleX) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleX, scaleX);
+ }
+ float getScaleY() const {
+ return mPrimitiveFields.scaleY;
+ }
+ void setScaleY(float scaleY) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleY, scaleY);
+ }
+ float getTranslateX() const {
+ return mPrimitiveFields.translateX;
+ }
+ void setTranslateX(float translateX) {
+ VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.translateX, translateX);
+ }
+ float getTranslateY() const {
+ return mPrimitiveFields.translateY;
+ }
+ void setTranslateY(float translateY) {
+ VD_SET_PROP_AND_NOTIFY(translateY, translateY);
+ }
+ void updateProperties(float rotate, float pivotX, float pivotY,
+ float scaleX, float scaleY, float translateX, float translateY) {
+ mPrimitiveFields.rotate = rotate;
+ mPrimitiveFields.pivotX = pivotX;
+ mPrimitiveFields.pivotY = pivotY;
+ mPrimitiveFields.scaleX = scaleX;
+ mPrimitiveFields.scaleY = scaleY;
+ mPrimitiveFields.translateX = translateX;
+ mPrimitiveFields.translateY = translateY;
+ onPropertyChanged();
+ }
+ void setPropertyValue(int propertyId, float value);
+ float getPropertyValue(int propertyId) const;
+ bool copyProperties(float* outProperties, int length) const;
+ static bool isValidProperty(int propertyId);
+ private:
+ enum class Property {
+ rotate = 0,
+ pivotX,
+ pivotY,
+ scaleX,
+ scaleY,
+ translateX,
+ translateY,
+ // Count of the properties, must be at the end.
+ count,
+ };
};
+
Group(const Group& group);
Group() {}
- float getRotation() {
- return mProperties.rotate;
- }
- void setRotation(float rotation) {
- mProperties.rotate = rotation;
- }
- float getPivotX() {
- return mProperties.pivotX;
- }
- void setPivotX(float pivotX) {
- mProperties.pivotX = pivotX;
- }
- float getPivotY() {
- return mProperties.pivotY;
- }
- void setPivotY(float pivotY) {
- mProperties.pivotY = pivotY;
- }
- float getScaleX() {
- return mProperties.scaleX;
- }
- void setScaleX(float scaleX) {
- mProperties.scaleX = scaleX;
- }
- float getScaleY() {
- return mProperties.scaleY;
- }
- void setScaleY(float scaleY) {
- mProperties.scaleY = scaleY;
- }
- float getTranslateX() {
- return mProperties.translateX;
- }
- void setTranslateX(float translateX) {
- mProperties.translateX = translateX;
- }
- float getTranslateY() {
- return mProperties.translateY;
- }
- void setTranslateY(float translateY) {
- mProperties.translateY = translateY;
+ void addChild(Node* child);
+ virtual void setPropertyChangedListener(PropertyChangedListener* listener) override {
+ Node::setPropertyChangedListener(listener);
+ for (auto& child : mChildren) {
+ child->setPropertyChangedListener(listener);
+ }
}
+ virtual void syncProperties() override;
+ GroupProperties* mutateStagingProperties() { return &mStagingProperties; }
+ const GroupProperties* stagingProperties() { return &mStagingProperties; }
+
+ // This should only be called from animations on RT
+ GroupProperties* mutateProperties() { return &mProperties; }
+
+ // Methods below could be called from either UI thread or Render Thread.
virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
- float scaleX, float scaleY) override;
- void updateLocalMatrix(float rotate, float pivotX, float pivotY,
- float scaleX, float scaleY, float translateX, float translateY);
- void getLocalMatrix(SkMatrix* outMatrix);
- void addChild(Node* child);
+ float scaleX, float scaleY, bool useStagingData) override;
+ void getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties);
void dump() override;
- bool getProperties(float* outProperties, int length);
- float getPropertyValue(int propertyId) const;
- void setPropertyValue(int propertyId, float value);
static bool isValidProperty(int propertyId);
+ virtual void onPropertyChanged(Properties* properties) override {
+ if (properties == &mStagingProperties) {
+ mStagingPropertiesDirty = true;
+ if (mPropertyChangedListener) {
+ mPropertyChangedListener->onStagingPropertyChanged();
+ }
+ } else {
+ if (mPropertyChangedListener) {
+ mPropertyChangedListener->onPropertyChanged();
+ }
+ }
+ }
+
private:
- enum class Property {
- Rotate = 0,
- PivotX,
- PivotY,
- ScaleX,
- ScaleY,
- TranslateX,
- TranslateY,
- // Count of the properties, must be at the end.
- Count,
- };
+ GroupProperties mProperties = GroupProperties(this);
+ GroupProperties mStagingProperties = GroupProperties(this);
+ bool mStagingPropertiesDirty = true;
std::vector< std::unique_ptr<Node> > mChildren;
- Properties mProperties;
};
class ANDROID_API Tree : public VirtualLightRefBase {
public:
- Tree(Group* rootNode) : mRootNode(rootNode) {}
+ Tree(Group* rootNode) : mRootNode(rootNode) {
+ mRootNode->setPropertyChangedListener(&mPropertyChangedListener);
+ }
void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
const SkRect& bounds, bool needsMirroring, bool canReuseCache);
+ void drawStaging(Canvas* canvas);
const SkBitmap& getBitmapUpdateIfDirty();
- void createCachedBitmapIfNeeded(int width, int height);
- bool canReuseBitmap(int width, int height);
void setAllowCaching(bool allowCaching) {
mAllowCaching = allowCaching;
}
- bool setRootAlpha(float rootAlpha) {
- return VD_SET_PROP(mRootAlpha, rootAlpha);
- }
-
- float getRootAlpha() {
- return mRootAlpha;
- }
- void setViewportSize(float viewportWidth, float viewportHeight) {
- mViewportWidth = viewportWidth;
- mViewportHeight = viewportHeight;
- }
SkPaint* getPaint();
- const SkRect& getBounds() const {
- return mBounds;
- }
+ void syncProperties() {
+ if (mStagingProperties.mNonAnimatablePropertiesDirty) {
+ mProperties.syncNonAnimatableProperties(mStagingProperties);
+ mStagingProperties.mNonAnimatablePropertiesDirty = false;
+ }
+
+ if (mStagingProperties.mAnimatablePropertiesDirty) {
+ mProperties.syncAnimatableProperties(mStagingProperties);
+ } else {
+ mStagingProperties.syncAnimatableProperties(mProperties);
+ }
+ mStagingProperties.mAnimatablePropertiesDirty = false;
+ mRootNode->syncProperties();
+ }
+
+ class TreeProperties {
+ public:
+ TreeProperties(Tree* tree) : mTree(tree) {}
+ // Properties that can only be modified by UI thread, therefore sync should
+ // only go from UI to RT
+ struct NonAnimatableProperties {
+ float viewportWidth = 0;
+ float viewportHeight = 0;
+ SkRect bounds;
+ int scaledWidth = 0;
+ int scaledHeight = 0;
+ SkColorFilter* colorFilter = nullptr;
+ ~NonAnimatableProperties() {
+ SkSafeUnref(colorFilter);
+ }
+ } mNonAnimatableProperties;
+ bool mNonAnimatablePropertiesDirty = true;
+
+ float mRootAlpha = 1.0f;
+ bool mAnimatablePropertiesDirty = true;
+
+ void syncNonAnimatableProperties(const TreeProperties& prop) {
+ // Copy over the data that can only be changed in UI thread
+ if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) {
+ SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter,
+ prop.mNonAnimatableProperties.colorFilter);
+ }
+ mNonAnimatableProperties = prop.mNonAnimatableProperties;
+ }
+
+ void setViewportSize(float width, float height) {
+ if (mNonAnimatableProperties.viewportWidth != width
+ || mNonAnimatableProperties.viewportHeight != height) {
+ mNonAnimatablePropertiesDirty = true;
+ mNonAnimatableProperties.viewportWidth = width;
+ mNonAnimatableProperties.viewportHeight = height;
+ mTree->onPropertyChanged(this);
+ }
+ }
+ void setBounds(const SkRect& bounds) {
+ if (mNonAnimatableProperties.bounds != bounds) {
+ mNonAnimatableProperties.bounds = bounds;
+ mNonAnimatablePropertiesDirty = true;
+ mTree->onPropertyChanged(this);
+ }
+ }
+
+ void setScaledSize(int width, int height) {
+ if (mNonAnimatableProperties.scaledWidth != width
+ || mNonAnimatableProperties.scaledHeight != height) {
+ mNonAnimatableProperties.scaledWidth = width;
+ mNonAnimatableProperties.scaledHeight = height;
+ mNonAnimatablePropertiesDirty = true;
+ mTree->onPropertyChanged(this);
+ }
+ }
+ void setColorFilter(SkColorFilter* filter) {
+ if (UPDATE_SKPROP(mNonAnimatableProperties.colorFilter, filter)) {
+ mNonAnimatablePropertiesDirty = true;
+ mTree->onPropertyChanged(this);
+ }
+ }
+ SkColorFilter* getColorFilter() const{
+ return mNonAnimatableProperties.colorFilter;
+ }
+
+ float getViewportWidth() const {
+ return mNonAnimatableProperties.viewportWidth;
+ }
+ float getViewportHeight() const {
+ return mNonAnimatableProperties.viewportHeight;
+ }
+ float getScaledWidth() const {
+ return mNonAnimatableProperties.scaledWidth;
+ }
+ float getScaledHeight() const {
+ return mNonAnimatableProperties.scaledHeight;
+ }
+ void syncAnimatableProperties(const TreeProperties& prop) {
+ mRootAlpha = prop.mRootAlpha;
+ }
+ bool setRootAlpha(float rootAlpha) {
+ if (rootAlpha != mRootAlpha) {
+ mAnimatablePropertiesDirty = true;
+ mRootAlpha = rootAlpha;
+ mTree->onPropertyChanged(this);
+ return true;
+ }
+ return false;
+ }
+ float getRootAlpha() const { return mRootAlpha;}
+ const SkRect& getBounds() const {
+ return mNonAnimatableProperties.bounds;
+ }
+ Tree* mTree;
+ };
+ void onPropertyChanged(TreeProperties* prop);
+ TreeProperties* mutateStagingProperties() { return &mStagingProperties; }
+ const TreeProperties* stagingProperties() { return &mStagingProperties; }
+ PushStagingFunctor* getFunctor() { return &mFunctor;}
+
+ // This should only be called from animations on RT
+ TreeProperties* mutateProperties() { return &mProperties; }
private:
+ class VectorDrawableFunctor : public PushStagingFunctor {
+ public:
+ VectorDrawableFunctor(Tree* tree) : mTree(tree) {}
+ virtual void operator ()() {
+ mTree->syncProperties();
+ }
+ private:
+ Tree* mTree;
+ };
+
+ SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
+ bool allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height);
+ bool canReuseBitmap(const SkBitmap&, int width, int height);
+ void updateBitmapCache(SkBitmap* outCache, bool useStagingData);
// Cap the bitmap size, such that it won't hurt the performance too much
// and it won't crash due to a very large scale.
// The drawable will look blurry above this size.
const static int MAX_CACHED_BITMAP_SIZE;
- bool mCacheDirty = true;
bool mAllowCaching = true;
- float mViewportWidth = 0;
- float mViewportHeight = 0;
- float mRootAlpha = 1.0f;
-
std::unique_ptr<Group> mRootNode;
- SkRect mBounds;
- SkMatrix mCanvasMatrix;
+
+ TreeProperties mProperties = TreeProperties(this);
+ TreeProperties mStagingProperties = TreeProperties(this);
+
+ VectorDrawableFunctor mFunctor = VectorDrawableFunctor(this);
+
SkPaint mPaint;
- SkPathMeasure mPathMeasure;
- SkBitmap mCachedBitmap;
+ struct Cache {
+ SkBitmap bitmap;
+ bool dirty = true;
+ };
+
+ Cache mStagingCache;
+ Cache mCache;
+ PropertyChangedListener mPropertyChangedListener
+ = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty);
};
} // namespace VectorDrawable
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index bb1a044a8369..73b6c02a3fdc 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -127,7 +127,7 @@ int OffscreenBufferPool::Entry::compare(const Entry& lhs, const Entry& rhs) {
}
void OffscreenBufferPool::clear() {
- for (auto entry : mPool) {
+ for (auto& entry : mPool) {
delete entry.layer;
}
mPool.clear();
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 7dfafb9117de..0ea246f00fb7 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -49,9 +49,12 @@ class TestRendererBase {
public:
virtual ~TestRendererBase() {}
virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) {
- ADD_FAILURE() << "Layer creation not expected in this test";
+ ADD_FAILURE() << "Temporary layers not expected in this test";
return nullptr;
}
+ virtual void recycleTemporaryLayer(OffscreenBuffer*) {
+ ADD_FAILURE() << "Temporary layers not expected in this test";
+ }
virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) {
ADD_FAILURE() << "Layer repaint not expected in this test";
}
@@ -298,7 +301,6 @@ RENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_bitmaps) {
class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase {
public:
void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
- EXPECT_LT(mIndex++, 2) << "Should be two bitmaps";
switch(mIndex++) {
case 0:
EXPECT_EQ(opaqueBitmap.pixelRef(), op.bitmap->pixelRef());
@@ -331,7 +333,7 @@ RENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_bitmaps) {
AvoidOverdrawBitmapsTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly one op";
+ EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops";
}
RENDERTHREAD_TEST(FrameBuilder, clippedMerging) {
@@ -711,6 +713,10 @@ RENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) {
EXPECT_EQ(Rect(200, 200), state.computedState.clipRect());
EXPECT_TRUE(state.computedState.transform.isIdentity());
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(4, mIndex++);
+ EXPECT_EQ(nullptr, offscreenBuffer);
+ }
};
auto node = TestUtils::createNode(0, 0, 200, 200,
@@ -723,7 +729,7 @@ RENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) {
TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(4, renderer.getIndex());
+ EXPECT_EQ(5, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) {
@@ -775,6 +781,15 @@ RENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) {
EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer
} else { ADD_FAILURE(); }
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ const int index = mIndex++;
+ // order isn't important, but we need to see both
+ if (index == 10) {
+ EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer);
+ } else if (index == 11) {
+ EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer);
+ } else { ADD_FAILURE(); }
+ }
};
auto node = TestUtils::createNode(0, 0, 800, 800,
@@ -795,7 +810,7 @@ RENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) {
TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerNestedTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(10, renderer.getIndex());
+ EXPECT_EQ(12, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) {
@@ -1010,10 +1025,15 @@ RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) {
}
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(9, mIndex++);
+ EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
}
void endFrame(const Rect& repaintRect) override {
EXPECT_EQ(11, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(12, mIndex++);
+ EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer);
+ }
};
auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping
@@ -1030,7 +1050,7 @@ RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) {
TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerUnclippedComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(12, renderer.getIndex());
+ EXPECT_EQ(13, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) {
@@ -1152,6 +1172,9 @@ RENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) {
void endFrame(const Rect& repaintRect) override {
EXPECT_EQ(12, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(13, mIndex++);
+ }
};
auto child = TestUtils::createNode(50, 50, 150, 150,
@@ -1189,7 +1212,7 @@ RENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) {
syncedList, sLightGeometry, Caches::getInstance());
HwLayerComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(13, renderer.getIndex());
+ EXPECT_EQ(14, renderer.getIndex());
// clean up layer pointers, so we can safely destruct RenderNodes
*(child->getLayerHandle()) = nullptr;
@@ -1593,6 +1616,9 @@ RENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) {
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(4, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(5, mIndex++);
+ }
};
auto parent = TestUtils::createNode(0, 0, 200, 200,
@@ -1611,7 +1637,7 @@ RENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) {
(FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
ShadowSaveLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(5, renderer.getIndex());
+ EXPECT_EQ(6, renderer.getIndex());
}
RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) {
@@ -1840,6 +1866,9 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(3, mIndex++);
}
+ void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(4, mIndex++);
+ }
private:
SaveLayerAlphaData* mOutData;
};
@@ -1865,7 +1894,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
// assert, since output won't be valid if we haven't seen a save layer triggered
- ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
+ ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
}
RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp
index 9161f90b54aa..e2fc376db50d 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -30,6 +30,25 @@ const LayerUpdateQueue sEmptyLayerUpdateQueue;
const FrameBuilder::LightGeometry sLightGeometery = { {100, 100, 100}, 50};
const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
+RENDERTHREAD_TEST(LeakCheck, saveLayer_overdrawRejection) {
+ auto node = TestUtils::createNode(0, 0, 100, 100,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(0, 0, 100, 100, 128, SaveFlags::ClipToLayer);
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ canvas.restore();
+
+ // opaque draw, rejects saveLayer beneath
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ });
+ RenderState& renderState = renderThread.renderState();
+ Caches& caches = Caches::getInstance();
+
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
+ TestUtils::createSyncedNodeList(node), sLightGeometery, Caches::getInstance());
+ BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
+ frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+}
+
RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) {
auto node = TestUtils::createNode(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 37a485e3a9ac..b7950aab5662 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -30,119 +30,126 @@ TEST(OffscreenBuffer, computeIdealDimension) {
EXPECT_EQ(1024u, OffscreenBuffer::computeIdealDimension(1000));
}
-TEST(OffscreenBuffer, construct) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBuffer layer(thread.renderState(), Caches::getInstance(), 49u, 149u);
- EXPECT_EQ(49u, layer.viewportWidth);
- EXPECT_EQ(149u, layer.viewportHeight);
+RENDERTHREAD_TEST(OffscreenBuffer, construct) {
+ OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 49u, 149u);
+ EXPECT_EQ(49u, layer.viewportWidth);
+ EXPECT_EQ(149u, layer.viewportHeight);
- EXPECT_EQ(64u, layer.texture.width());
- EXPECT_EQ(192u, layer.texture.height());
+ EXPECT_EQ(64u, layer.texture.width());
+ EXPECT_EQ(192u, layer.texture.height());
- EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes());
- });
+ EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes());
}
-TEST(OffscreenBuffer, getTextureCoordinates) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBuffer layerAligned(thread.renderState(), Caches::getInstance(), 256u, 256u);
- EXPECT_EQ(Rect(0, 1, 1, 0),
- layerAligned.getTextureCoordinates());
+RENDERTHREAD_TEST(OffscreenBuffer, getTextureCoordinates) {
+ OffscreenBuffer layerAligned(renderThread.renderState(), Caches::getInstance(), 256u, 256u);
+ EXPECT_EQ(Rect(0, 1, 1, 0),
+ layerAligned.getTextureCoordinates());
- OffscreenBuffer layerUnaligned(thread.renderState(), Caches::getInstance(), 200u, 225u);
- EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
- layerUnaligned.getTextureCoordinates());
- });
+ OffscreenBuffer layerUnaligned(renderThread.renderState(), Caches::getInstance(), 200u, 225u);
+ EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
+ layerUnaligned.getTextureCoordinates());
}
-TEST(OffscreenBuffer, dirty) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBuffer buffer(thread.renderState(), Caches::getInstance(), 256u, 256u);
- buffer.dirty(Rect(-100, -100, 100, 100));
- EXPECT_EQ(android::Rect(100, 100), buffer.region.getBounds());
- });
+RENDERTHREAD_TEST(OffscreenBuffer, dirty) {
+ OffscreenBuffer buffer(renderThread.renderState(), Caches::getInstance(), 256u, 256u);
+ buffer.dirty(Rect(-100, -100, 100, 100));
+ EXPECT_EQ(android::Rect(100, 100), buffer.region.getBounds());
}
-TEST(OffscreenBufferPool, construct) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
- EXPECT_EQ(0u, pool.getCount()) << "pool must be created empty";
- EXPECT_EQ(0u, pool.getSize()) << "pool must be created empty";
- EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize())
- << "pool must read size from Properties";
- });
+RENDERTHREAD_TEST(OffscreenBufferPool, construct) {
+ OffscreenBufferPool pool;
+ EXPECT_EQ(0u, pool.getCount()) << "pool must be created empty";
+ EXPECT_EQ(0u, pool.getSize()) << "pool must be created empty";
+ EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize())
+ << "pool must read size from Properties";
}
-TEST(OffscreenBufferPool, getPutClear) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
+RENDERTHREAD_TEST(OffscreenBufferPool, getPutClear) {
+ OffscreenBufferPool pool;
- auto layer = pool.get(thread.renderState(), 100u, 200u);
- EXPECT_EQ(100u, layer->viewportWidth);
- EXPECT_EQ(200u, layer->viewportHeight);
+ auto layer = pool.get(renderThread.renderState(), 100u, 200u);
+ EXPECT_EQ(100u, layer->viewportWidth);
+ EXPECT_EQ(200u, layer->viewportHeight);
- ASSERT_LT(layer->getSizeInBytes(), pool.getMaxSize());
+ ASSERT_LT(layer->getSizeInBytes(), pool.getMaxSize());
- pool.putOrDelete(layer);
- ASSERT_EQ(layer->getSizeInBytes(), pool.getSize());
+ pool.putOrDelete(layer);
+ ASSERT_EQ(layer->getSizeInBytes(), pool.getSize());
- auto layer2 = pool.get(thread.renderState(), 102u, 202u);
- EXPECT_EQ(layer, layer2) << "layer should be recycled";
- ASSERT_EQ(0u, pool.getSize()) << "pool should have been emptied by removing only layer";
+ auto layer2 = pool.get(renderThread.renderState(), 102u, 202u);
+ EXPECT_EQ(layer, layer2) << "layer should be recycled";
+ ASSERT_EQ(0u, pool.getSize()) << "pool should have been emptied by removing only layer";
- pool.putOrDelete(layer);
- EXPECT_EQ(1u, pool.getCount());
- pool.clear();
- EXPECT_EQ(0u, pool.getSize());
- EXPECT_EQ(0u, pool.getCount());
- });
+ pool.putOrDelete(layer);
+ EXPECT_EQ(1u, pool.getCount());
+ pool.clear();
+ EXPECT_EQ(0u, pool.getSize());
+ EXPECT_EQ(0u, pool.getCount());
}
-TEST(OffscreenBufferPool, resize) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
-
- auto layer = pool.get(thread.renderState(), 64u, 64u);
- layer->dirty(Rect(64, 64));
-
- // resize in place
- ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
- EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
- EXPECT_EQ(60u, layer->viewportWidth);
- EXPECT_EQ(55u, layer->viewportHeight);
- EXPECT_EQ(64u, layer->texture.width());
- EXPECT_EQ(64u, layer->texture.height());
-
- // resized to use different object in pool
- auto layer2 = pool.get(thread.renderState(), 128u, 128u);
- layer2->dirty(Rect(128, 128));
- EXPECT_FALSE(layer2->region.isEmpty());
- pool.putOrDelete(layer2);
- ASSERT_EQ(1u, pool.getCount());
-
- ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
- EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
- EXPECT_EQ(120u, layer2->viewportWidth);
- EXPECT_EQ(125u, layer2->viewportHeight);
- EXPECT_EQ(128u, layer2->texture.width());
- EXPECT_EQ(128u, layer2->texture.height());
-
- // original allocation now only thing in pool
- EXPECT_EQ(1u, pool.getCount());
- EXPECT_EQ(layer->getSizeInBytes(), pool.getSize());
-
- pool.putOrDelete(layer2);
- });
+RENDERTHREAD_TEST(OffscreenBufferPool, resize) {
+ OffscreenBufferPool pool;
+
+ auto layer = pool.get(renderThread.renderState(), 64u, 64u);
+ layer->dirty(Rect(64, 64));
+
+ // resize in place
+ ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
+ EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
+ EXPECT_EQ(60u, layer->viewportWidth);
+ EXPECT_EQ(55u, layer->viewportHeight);
+ EXPECT_EQ(64u, layer->texture.width());
+ EXPECT_EQ(64u, layer->texture.height());
+
+ // resized to use different object in pool
+ auto layer2 = pool.get(renderThread.renderState(), 128u, 128u);
+ layer2->dirty(Rect(128, 128));
+ EXPECT_FALSE(layer2->region.isEmpty());
+ pool.putOrDelete(layer2);
+ ASSERT_EQ(1u, pool.getCount());
+
+ ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
+ EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
+ EXPECT_EQ(120u, layer2->viewportWidth);
+ EXPECT_EQ(125u, layer2->viewportHeight);
+ EXPECT_EQ(128u, layer2->texture.width());
+ EXPECT_EQ(128u, layer2->texture.height());
+
+ // original allocation now only thing in pool
+ EXPECT_EQ(1u, pool.getCount());
+ EXPECT_EQ(layer->getSizeInBytes(), pool.getSize());
+
+ pool.putOrDelete(layer2);
}
-TEST(OffscreenBufferPool, putAndDestroy) {
- TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
- OffscreenBufferPool pool;
- // layer too big to return to the pool
- // Note: this relies on the fact that the pool won't reject based on max texture size
- auto hugeLayer = pool.get(thread.renderState(), pool.getMaxSize() / 64, 64);
- EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize());
- pool.putOrDelete(hugeLayer);
- EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
- });
+RENDERTHREAD_TEST(OffscreenBufferPool, putAndDestroy) {
+ OffscreenBufferPool pool;
+ // layer too big to return to the pool
+ // Note: this relies on the fact that the pool won't reject based on max texture size
+ auto hugeLayer = pool.get(renderThread.renderState(), pool.getMaxSize() / 64, 64);
+ EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize());
+ pool.putOrDelete(hugeLayer);
+ EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
+}
+
+RENDERTHREAD_TEST(OffscreenBufferPool, clear) {
+ EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
+ OffscreenBufferPool pool;
+
+ // Create many buffers, with several at each size
+ std::vector<OffscreenBuffer*> buffers;
+ for (int size = 32; size <= 128; size += 32) {
+ for (int i = 0; i < 10; i++) {
+ buffers.push_back(pool.get(renderThread.renderState(), size, size));
+ }
+ }
+ EXPECT_EQ(0u, pool.getCount()) << "Expect nothing inside";
+ for (auto& buffer : buffers) pool.putOrDelete(buffer);
+ EXPECT_EQ(40u, pool.getCount()) << "Expect all items added";
+ EXPECT_EQ(40, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
+ pool.clear();
+ EXPECT_EQ(0u, pool.getCount()) << "Expect all items cleared";
+
+ EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
}
diff --git a/media/java/android/media/DrmInitData.java b/media/java/android/media/DrmInitData.java
index 06fe6ffb0d06..170d9de9d50a 100644
--- a/media/java/android/media/DrmInitData.java
+++ b/media/java/android/media/DrmInitData.java
@@ -28,6 +28,12 @@ import java.util.UUID;
public abstract class DrmInitData {
/**
+ * Prevent public constuctor access
+ */
+ /* package private */ DrmInitData() {
+ }
+
+ /**
* Retrieves initialization data for a given DRM scheme, specified by its UUID.
*
* @param schemeUuid The DRM scheme's UUID.
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index 1fee58707613..983ca754acd1 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -45,8 +45,7 @@ public class MediaActionSound {
private static final int NUM_MEDIA_SOUND_STREAMS = 1;
private SoundPool mSoundPool;
- private int[] mSoundIds;
- private int mSoundIdToPlay;
+ private SoundState[] mSounds;
private static final String[] SOUND_FILES = {
"/system/media/audio/ui/camera_click.ogg",
@@ -88,22 +87,57 @@ public class MediaActionSound {
*/
public static final int STOP_VIDEO_RECORDING = 3;
- private static final int SOUND_NOT_LOADED = -1;
+ /**
+ * States for SoundState.
+ * STATE_NOT_LOADED : sample not loaded
+ * STATE_LOADING : sample being loaded: waiting for load completion callback
+ * STATE_LOADING_PLAY_REQUESTED : sample being loaded and playback request received
+ * STATE_LOADED : sample loaded, ready for playback
+ */
+ private static final int STATE_NOT_LOADED = 0;
+ private static final int STATE_LOADING = 1;
+ private static final int STATE_LOADING_PLAY_REQUESTED = 2;
+ private static final int STATE_LOADED = 3;
+
+ private class SoundState {
+ public final int name;
+ public int id;
+ public int state;
+ public SoundState(int name) {
+ this.name = name;
+ id = 0; // 0 is an invalid sample ID.
+ state = STATE_NOT_LOADED;
+ }
+ }
/**
* Construct a new MediaActionSound instance. Only a single instance is
* needed for playing any platform media action sound; you do not need a
* separate instance for each sound type.
*/
public MediaActionSound() {
- mSoundPool = new SoundPool(NUM_MEDIA_SOUND_STREAMS,
- AudioManager.STREAM_SYSTEM_ENFORCED, 0);
+ mSoundPool = new SoundPool.Builder()
+ .setMaxStreams(NUM_MEDIA_SOUND_STREAMS)
+ .setAudioAttributes(new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .build())
+ .build();
mSoundPool.setOnLoadCompleteListener(mLoadCompleteListener);
- mSoundIds = new int[SOUND_FILES.length];
- for (int i = 0; i < mSoundIds.length; i++) {
- mSoundIds[i] = SOUND_NOT_LOADED;
+ mSounds = new SoundState[SOUND_FILES.length];
+ for (int i = 0; i < mSounds.length; i++) {
+ mSounds[i] = new SoundState(i);
}
- mSoundIdToPlay = SOUND_NOT_LOADED;
+ }
+
+ private int loadSound(SoundState sound) {
+ int id = mSoundPool.load(SOUND_FILES[sound.name], 1);
+ if (id > 0) {
+ sound.state = STATE_LOADING;
+ sound.id = id;
+ }
+ return id;
}
/**
@@ -118,13 +152,22 @@ public class MediaActionSound {
* @see #START_VIDEO_RECORDING
* @see #STOP_VIDEO_RECORDING
*/
- public synchronized void load(int soundName) {
+ public void load(int soundName) {
if (soundName < 0 || soundName >= SOUND_FILES.length) {
throw new RuntimeException("Unknown sound requested: " + soundName);
}
- if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
- mSoundIds[soundName] =
- mSoundPool.load(SOUND_FILES[soundName], 1);
+ SoundState sound = mSounds[soundName];
+ synchronized (sound) {
+ switch (sound.state) {
+ case STATE_NOT_LOADED:
+ if (loadSound(sound) <= 0) {
+ Log.e(TAG, "load() error loading sound: " + soundName);
+ }
+ break;
+ default:
+ Log.e(TAG, "load() called in wrong state: " + sound + " for sound: "+ soundName);
+ break;
+ }
}
}
@@ -159,16 +202,31 @@ public class MediaActionSound {
* @see #START_VIDEO_RECORDING
* @see #STOP_VIDEO_RECORDING
*/
- public synchronized void play(int soundName) {
+ public void play(int soundName) {
if (soundName < 0 || soundName >= SOUND_FILES.length) {
throw new RuntimeException("Unknown sound requested: " + soundName);
}
- if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
- mSoundIdToPlay =
- mSoundPool.load(SOUND_FILES[soundName], 1);
- mSoundIds[soundName] = mSoundIdToPlay;
- } else {
- mSoundPool.play(mSoundIds[soundName], 1.0f, 1.0f, 0, 0, 1.0f);
+ SoundState sound = mSounds[soundName];
+ synchronized (sound) {
+ switch (sound.state) {
+ case STATE_NOT_LOADED:
+ loadSound(sound);
+ if (loadSound(sound) <= 0) {
+ Log.e(TAG, "play() error loading sound: " + soundName);
+ break;
+ }
+ // FALL THROUGH
+
+ case STATE_LOADING:
+ sound.state = STATE_LOADING_PLAY_REQUESTED;
+ break;
+ case STATE_LOADED:
+ mSoundPool.play(sound.id, 1.0f, 1.0f, 0, 0, 1.0f);
+ break;
+ default:
+ Log.e(TAG, "play() called in wrong state: " + sound.state + " for sound: "+ soundName);
+ break;
+ }
}
}
@@ -176,14 +234,37 @@ public class MediaActionSound {
new SoundPool.OnLoadCompleteListener() {
public void onLoadComplete(SoundPool soundPool,
int sampleId, int status) {
- if (status == 0) {
- if (mSoundIdToPlay == sampleId) {
- soundPool.play(sampleId, 1.0f, 1.0f, 0, 0, 1.0f);
- mSoundIdToPlay = SOUND_NOT_LOADED;
+ for (SoundState sound : mSounds) {
+ if (sound.id != sampleId) {
+ continue;
}
- } else {
- Log.e(TAG, "Unable to load sound for playback (status: " +
- status + ")");
+ int playSoundId = 0;
+ synchronized (sound) {
+ if (status != 0) {
+ sound.state = STATE_NOT_LOADED;
+ sound.id = 0;
+ Log.e(TAG, "OnLoadCompleteListener() error: " + status +
+ " loading sound: "+ sound.name);
+ return;
+ }
+ switch (sound.state) {
+ case STATE_LOADING:
+ sound.state = STATE_LOADED;
+ break;
+ case STATE_LOADING_PLAY_REQUESTED:
+ playSoundId = sound.id;
+ sound.state = STATE_LOADED;
+ break;
+ default:
+ Log.e(TAG, "OnLoadCompleteListener() called in wrong state: "
+ + sound.state + " for sound: "+ sound.name);
+ break;
+ }
+ }
+ if (playSoundId != 0) {
+ soundPool.play(playSoundId, 1.0f, 1.0f, 0, 0, 1.0f);
+ }
+ break;
}
}
};
@@ -195,6 +276,12 @@ public class MediaActionSound {
*/
public void release() {
if (mSoundPool != null) {
+ for (SoundState sound : mSounds) {
+ synchronized (sound) {
+ sound.state = STATE_NOT_LOADED;
+ sound.id = 0;
+ }
+ }
mSoundPool.release();
mSoundPool = null;
}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 177344a0ed4c..24a400e48189 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -275,16 +275,23 @@ final public class MediaExtractor {
return initDataMap.get(schemeUuid);
}
};
- } else if (formatMap.containsKey("crypto-key")) {
- ByteBuffer buf = (ByteBuffer) formatMap.get("crypto-key");
- buf.rewind();
- final byte[] data = new byte[buf.remaining()];
- buf.get(data);
- return new DrmInitData() {
- public SchemeInitData get(UUID schemeUuid) {
- return new DrmInitData.SchemeInitData("webm", data);
+ } else {
+ int numTracks = getTrackCount();
+ for (int i = 0; i < numTracks; ++i) {
+ Map<String, Object> trackFormatMap = getTrackFormatNative(i);
+ if (!trackFormatMap.containsKey("crypto-key")) {
+ continue;
}
- };
+ ByteBuffer buf = (ByteBuffer) trackFormatMap.get("crypto-key");
+ buf.rewind();
+ final byte[] data = new byte[buf.remaining()];
+ buf.get(data);
+ return new DrmInitData() {
+ public SchemeInitData get(UUID schemeUuid) {
+ return new DrmInitData.SchemeInitData("webm", data);
+ }
+ };
+ }
}
return null;
}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index c1805cb5713f..7c6adadc2c6a 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -72,7 +72,7 @@ public final class MediaBrowser {
/**
* Used as an int extra field to denote the page number to subscribe.
- * The value of {@code EXTRA_PAGE} should be greater than or equal to 1.
+ * The value of {@code EXTRA_PAGE} should be greater than or equal to 0.
*
* @see #EXTRA_PAGE_SIZE
*/
diff --git a/media/java/android/media/browse/MediaBrowserUtils.java b/media/java/android/media/browse/MediaBrowserUtils.java
index b06e598a63d1..2943e60dbbbd 100644
--- a/media/java/android/media/browse/MediaBrowserUtils.java
+++ b/media/java/android/media/browse/MediaBrowserUtils.java
@@ -50,7 +50,7 @@ public class MediaBrowserUtils {
startIndex1 = 0;
endIndex1 = Integer.MAX_VALUE;
} else {
- startIndex1 = pageSize1 * (page1 - 1);
+ startIndex1 = pageSize1 * page1;
endIndex1 = startIndex1 + pageSize1 - 1;
}
@@ -58,7 +58,7 @@ public class MediaBrowserUtils {
startIndex2 = 0;
endIndex2 = Integer.MAX_VALUE;
} else {
- startIndex2 = pageSize2 * (page2 - 1);
+ startIndex2 = pageSize2 * page2;
endIndex2 = startIndex2 + pageSize2 - 1;
}
diff --git a/media/java/android/media/midi/IMidiDeviceServer.aidl b/media/java/android/media/midi/IMidiDeviceServer.aidl
index c2cc2b9f9379..d5115de4a048 100644
--- a/media/java/android/media/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/midi/IMidiDeviceServer.aidl
@@ -28,7 +28,8 @@ interface IMidiDeviceServer
void closeDevice();
// connects the input port pfd to the specified output port
- void connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
+ // Returns the PID of the called process.
+ int connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
MidiDeviceInfo getDeviceInfo();
void setDeviceInfo(in MidiDeviceInfo deviceInfo);
diff --git a/media/java/android/media/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
index e1990cd6fbbb..e4588fe3abc5 100644
--- a/media/java/android/media/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -19,6 +19,7 @@ package android.media.midi;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
@@ -181,9 +182,16 @@ public final class MidiDevice implements Closeable {
}
try {
IBinder token = new Binder();
- mDeviceServer.connectPorts(token, pfd, outputPortNumber);
- // close our copy of the file descriptor
- IoUtils.closeQuietly(pfd);
+ int calleePid = mDeviceServer.connectPorts(token, pfd, outputPortNumber);
+ // If the service is a different Process then it will duplicate the pfd
+ // and we can safely close this one.
+ // But if the service is in the same Process then closing the pfd will
+ // kill the connection. So don't do that.
+ if (calleePid != Process.myPid()) {
+ // close our copy of the file descriptor
+ IoUtils.closeQuietly(pfd);
+ }
+
return new MidiConnection(token, inputPort);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in connectPorts");
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index 19ff62460155..f0abf711ba16 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -254,7 +254,7 @@ public final class MidiDeviceServer implements Closeable {
}
@Override
- public void connectPorts(IBinder token, ParcelFileDescriptor pfd,
+ public int connectPorts(IBinder token, ParcelFileDescriptor pfd,
int outputPortNumber) {
MidiInputPort inputPort = new MidiInputPort(pfd, outputPortNumber);
MidiDispatcher dispatcher = mOutputPortDispatchers[outputPortNumber];
@@ -270,6 +270,7 @@ public final class MidiDeviceServer implements Closeable {
synchronized (mPortClients) {
mPortClients.put(token, client);
}
+ return Process.myPid(); // for caller to detect same process ID
}
@Override
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index ae8663269bd3..6954045574a5 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -657,9 +657,9 @@ public abstract class MediaBrowserService extends Service {
if (page == -1 && pageSize == -1) {
return list;
}
- int fromIndex = pageSize * (page - 1);
+ int fromIndex = pageSize * page;
int toIndex = fromIndex + pageSize;
- if (page < 1 || pageSize < 1 || fromIndex >= list.size()) {
+ if (page < 0 || pageSize < 1 || fromIndex >= list.size()) {
return Collections.EMPTY_LIST;
}
if (toIndex > list.size()) {
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 5722cb013026..39f2a326f543 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -882,7 +882,7 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
break;
}
- info.mThumbCompressedSize = image_data.thumbnail_length;
+ info.mThumbCompressedSize = image_data.thumbnail.length;
info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
info.mImagePixWidth = image_data.full_width;
info.mImagePixHeight = image_data.full_height;
@@ -932,19 +932,19 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)
break;
}
- if (image_data.thumbnail_length == 0) {
+ if (image_data.thumbnail.length == 0) {
// No thumbnail.
break;
}
- result = malloc(image_data.thumbnail_length);
+ result = malloc(image_data.thumbnail.length);
if (result) {
piex::Error err = stream.get()->GetData(
- image_data.thumbnail_offset,
- image_data.thumbnail_length,
+ image_data.thumbnail.offset,
+ image_data.thumbnail.length,
(std::uint8_t *)result);
if (err == piex::Error::kOk) {
- outThumbSize = image_data.thumbnail_length;
+ outThumbSize = image_data.thumbnail.length;
} else {
free(result);
}
diff --git a/packages/CtsShim/Android.mk b/packages/CtsShim/Android.mk
new file mode 100644
index 000000000000..537b1714ba71
--- /dev/null
+++ b/packages/CtsShim/Android.mk
@@ -0,0 +1,61 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+###########################################################
+# Variant: Privileged app
+
+include $(CLEAR_VARS)
+# this needs to be a privileged application
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := current
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PACKAGE_NAME := CtsShimPriv
+
+#TODO need to find the correct certificate
+#Change in conjunction with cts/hostsidetests/appsecurity/test-apps/IntentFilterApp
+LOCAL_CERTIFICATE := platform
+LOCAL_MANIFEST_FILE := priv_shim/AndroidManifest.xml
+
+include $(BUILD_PACKAGE)
+
+
+
+###########################################################
+# Variant: System app
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := current
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PACKAGE_NAME := CtsShim
+
+#TODO need to find the correct certificate
+#Change in conjunction with cts/hostsidetests/appsecurity/test-apps/IntentFilterApp
+LOCAL_CERTIFICATE := platform
+LOCAL_MANIFEST_FILE := shim/AndroidManifest.xml
+
+include $(BUILD_PACKAGE)
+
+
diff --git a/packages/CtsShim/priv_shim/AndroidManifest.xml b/packages/CtsShim/priv_shim/AndroidManifest.xml
new file mode 100644
index 000000000000..0a3f8235948c
--- /dev/null
+++ b/packages/CtsShim/priv_shim/AndroidManifest.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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 for the privileged CTS shim -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.priv.ctsshim">
+ <application android:label="CtsShim">
+
+ <!-- These activities don't actually exist; define them just to test the filters !-->
+
+ <!-- install test; [some] high priority filters granted -->
+ <activity android:name=".InstallPriority">
+ <!-- normal actions; priority will be granted -->
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SEARCH" />
+ <category android:name="android.intent.category.INFO" />
+ </intent-filter>
+
+ <!-- protected actions; priority will be denied -->
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SEND" />
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SEND_MULTIPLE" />
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SENDTO" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; single, equivalent filter -->
+ <activity android:name=".UpgradeMatch">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.MATCH" />
+ <category android:name="android.intent.category.INFO" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; multiple, equivalent filters -->
+ <activity android:name=".UpgradeMatchMultiple">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.MATCH_MULTIPLE" />
+ <category android:name="android.intent.category.INFO" />
+ </intent-filter>
+
+ <intent-filter android:priority="150">
+ <action android:name="com.android.cts.action.MATCH_MULTIPLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:host="www.google.com" android:port="80" />
+ <data android:host="www.google.com" android:port="8080" />
+ <data android:host="goo.gl" android:port="443" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; lower priority -->
+ <activity android:name=".UpgradeLowerPriority">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.LOWER_PRIORITY" />
+ <category android:name="android.intent.category.INFO" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; action subset -->
+ <activity android:name=".UpgradeActionSubset">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.ACTION_SUB" />
+ <action android:name="com.android.cts.action.ACTION_SUB_2" />
+ <action android:name="com.android.cts.action.ACTION_SUB_3" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; category subset -->
+ <activity android:name=".UpgradeCategorySubset">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.CATEGORY_SUB" />
+ <category android:name="android.intent.category.INFO" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; scheme subset -->
+ <activity android:name=".UpgradeSchemeSubset">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.SCHEME_SUB" />
+ <data android:scheme="content" />
+ <data android:scheme="flubber" />
+ <data android:scheme="zoodle" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; authority subset -->
+ <activity android:name=".UpgradeAuthoritySubset">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.AUTHORITY_SUB" />
+ <data android:host="www.google.com" android:port="80" />
+ <data android:host="www.google.com" android:port="8080" />
+ <data android:host="mail.google.com" android:port="80" />
+ <data android:host="goo.gl" android:port="443" />
+ </intent-filter>
+ </activity>
+
+
+ <!-- upgrade test; new action -->
+ <activity android:name=".UpgradeNewAction">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.NEW_ACTION" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; new category -->
+ <activity android:name=".UpgradeNewCategory">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.NEW_CATEGORY" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; new scheme -->
+ <activity android:name=".UpgradeNewScheme">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.NEW_SCHEME" />
+ <data android:scheme="content" />
+ </intent-filter>
+ </activity>
+
+ <!-- upgrade test; new authority -->
+ <activity android:name=".UpgradeNewAuthority">
+ <intent-filter android:priority="100">
+ <action android:name="com.android.cts.action.NEW_AUTHORITY" />
+ <data android:host="www.google.com" android:port="80" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
+
diff --git a/packages/CtsShim/shim/AndroidManifest.xml b/packages/CtsShim/shim/AndroidManifest.xml
new file mode 100644
index 000000000000..ee4b547ddc97
--- /dev/null
+++ b/packages/CtsShim/shim/AndroidManifest.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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 for the system CTS shim -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.system.ctsshim">
+ <application android:label="CtsShim">
+
+ <!-- These activities don't actually exist; define them just to test the filters !-->
+
+ <!-- install test; high priority filter DENIED -->
+ <activity android:name=".InstallPriority">
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SEARCH" />
+ <category android:name="android.intent.category.INFO" />
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SEND" />
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SEND_MULTIPLE" />
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.SENDTO" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
+
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 14609b21d19d..69912ab12098 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -43,9 +43,9 @@
<activity
android:name=".LauncherActivity"
- android:theme="@android:style/Theme.NoDisplay"
- android:icon="@mipmap/ic_launcher_download"
- android:label="@string/downloads_label">
+ android:label="@string/downloads_label"
+ android:icon="@mipmap/ic_launcher_downloads"
+ android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -54,21 +54,21 @@
<activity
android:name=".FilesActivity"
- android:theme="@style/DocumentsTheme"
- android:icon="@mipmap/ic_launcher_download"
android:label="@string/downloads_label"
- android:documentLaunchMode="intoExisting">
+ android:icon="@mipmap/ic_launcher_downloads"
+ android:documentLaunchMode="intoExisting"
+ android:theme="@style/DocumentsTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<intent-filter>
- <action android:name="android.intent.action.VIEW_DOWNLOADS" />
+ <action android:name="android.provider.action.BROWSE" />
<category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.document/root" />
</intent-filter>
<intent-filter>
- <action android:name="android.provider.action.BROWSE" />
+ <action android:name="android.intent.action.VIEW_DOWNLOADS" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.document/root" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
diff --git a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
index 1c3ed80adc2f..0013b6b7be7e 100644
--- a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
+++ b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.documentsui.appperftests">
+ <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
<application>
<uses-library android:name="android.test.runner" />
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
index d6e8a96f3ad1..ce2fc13bc55a 100644
--- a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
@@ -17,6 +17,8 @@
package com.android.documentsui;
import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -91,12 +93,15 @@ public class FilesAppPerfTest extends InstrumentationTestCase {
}
private void killProviders() throws Exception {
- final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+ final Context context = getInstrumentation().getContext();
+ final PackageManager pm = context.getPackageManager();
+ final ActivityManager am = (ActivityManager) context.getSystemService(
+ Context.ACTIVITY_SERVICE);
final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0);
for (ResolveInfo info : providers) {
final String packageName = info.providerInfo.packageName;
- mDevice.executeShellCommand("am force-stop " + packageName);
+ am.killBackgroundProcesses(packageName);
}
}
}
diff --git a/packages/DocumentsUI/res/drawable/drag_shadow_background.xml b/packages/DocumentsUI/res/drawable/drag_shadow_background.xml
new file mode 100644
index 000000000000..49465cbabe3c
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/drag_shadow_background.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/item_doc_background" />
+ <stroke
+ android:width="1dp"
+ android:color="#ff9f9f9f" />
+ <corners
+ android:bottomRightRadius="3dp"
+ android:bottomLeftRadius="3dp"
+ android:topLeftRadius="3dp"
+ android:topRightRadius="3dp"/>
+</shape>
diff --git a/packages/DocumentsUI/res/layout/drag_shadow_layout.xml b/packages/DocumentsUI/res/layout/drag_shadow_layout.xml
new file mode 100644
index 000000000000..26613efddf14
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/drag_shadow_layout.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:orientation="horizontal"
+ android:gravity="center_vertical|left"
+ android:background="@drawable/drag_shadow_background">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/root_icon_size"
+ android:layout_height="@dimen/root_icon_size"
+ android:scaleType="centerInside"
+ android:contentDescription="@null"
+ android:duplicateParentState="true"/>
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:textAlignment="viewStart"
+ android:textColor="@color/item_title"
+ android:paddingStart="8dp"/>
+
+</LinearLayout>
diff --git a/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_downloads.png
index f958bbd3c255..f958bbd3c255 100644
--- a/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png
+++ b/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_downloads.png
index f2e937663c2c..f2e937663c2c 100644
--- a/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png
+++ b/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_downloads.png
index 4dc533638757..4dc533638757 100644
--- a/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png
+++ b/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_downloads.png
index 8716290969da..8716290969da 100644
--- a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png
+++ b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_downloads.png
index f5be21991761..f5be21991761 100644
--- a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png
+++ b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index 75d9b4b63b2e..1a7c6205cd2c 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Kon nie dokument hernoem nie"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige lêers is omgeskakel"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Gee <xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang tot <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-gids op <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Gee <xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang tot <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-gids?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Gee <xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang tot jou data, insluitend foto\'s en video\'s, op <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Moenie weer vra nie"</string>
<string name="allow" msgid="7225948811296386551">"Laat toe"</string>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index 922b9cae0489..ca43dab34477 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ሰነዱን ዳግም መሰየም አልተሳካም"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"አንዳንድ ፋይሎች ተለውጠዋል"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> በ<xliff:g id="STORAGE"><i>^3</i></xliff:g> ላይ የ<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ማውጫ መደረሻ ይሰጠው?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"የ<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ማውጫ መዳረሻ ለ<xliff:g id="APPNAME"><b>^1</b></xliff:g> ይሰጠው?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"በ<xliff:g id="STORAGE"><i>^2</i></xliff:g> ላይ ያሉትን ፎቶዎች እና ቪዲዮዎች ጨምሮ የውሂብዎ መዳረሻ ለ<xliff:g id="APPNAME"><b>^1</b></xliff:g> ይሰጥ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"ዳግም አትጠይቅ"</string>
<string name="allow" msgid="7225948811296386551">"ይፍቀዱ"</string>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index f48c542ce3af..e6fac5093698 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -139,6 +139,7 @@
<string name="rename_error" msgid="4203041674883412606">"أخفقت إعادة تسمية المستند."</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"تم تحويل بعض الملفات"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"هل تريد منح التطبيق <xliff:g id="APPNAME"><b>^1</b></xliff:g> حق الوصول إلى الدليل <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> على <xliff:g id="STORAGE"><i>^3</i></xliff:g>؟"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"هل تريد تمكين <xliff:g id="APPNAME"><b>^1</b></xliff:g> من الدخول إلى دليل <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>؟"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"هل تريد منح <xliff:g id="APPNAME"><b>^1</b></xliff:g> حق الوصول إلى بياناتك، بما في ذلك الصور ومقاطع الفيديو على <xliff:g id="STORAGE"><i>^2</i></xliff:g>؟"</string>
<string name="never_ask_again" msgid="4295278542972859268">"عدم السؤال مرة أخرى"</string>
<string name="allow" msgid="7225948811296386551">"السماح"</string>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index a4d6f518dd63..75a0686c7ffd 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Sənəd adını dəyişmək uğursuz oldu"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bəzi fayllar konvertasiya edilib"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> yaddaşında <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> kataloquna <xliff:g id="APPNAME"><b>^1</b></xliff:g> girişi təqdim edilsin?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> kataloquna <xliff:g id="APPNAME"><b>^1</b></xliff:g> girişi təqdim edilsin?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> yaddaşında foto və videolar daxil olmaqla datanıza <xliff:g id="APPNAME"><b>^1</b></xliff:g> girişi təmin edilsin?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Bir daha soruşmayın"</string>
<string name="allow" msgid="7225948811296386551">"İcazə verin"</string>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 2c4fe5c89c2f..34c08bddfc14 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -118,6 +118,7 @@
<string name="rename_error" msgid="4203041674883412606">"Preimenovanje dokumenta nije uspelo"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke datoteke su konvertovane"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Želite li da aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> odobrite pristup direktorijumu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> na memorijskom prostoru <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Želite da dozvolite da <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristupa direktorijumu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Želite da li da dozvolite da aplikacija <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristupa podacima, uključujući slike i video snimke, na lokaciji <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ne pitaj ponovo"</string>
<string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
diff --git a/packages/DocumentsUI/res/values-be-rBY/strings.xml b/packages/DocumentsUI/res/values-be-rBY/strings.xml
index 6e4113e8e0b1..8493c4772039 100644
--- a/packages/DocumentsUI/res/values-be-rBY/strings.xml
+++ b/packages/DocumentsUI/res/values-be-rBY/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Не атрымалася перайменаваць дакумент"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некаторыя файлы былі сканвертаваныя"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Даць праграме <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да дырэкторыі <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> у <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Даць праграме <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да дырэкторыі <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Даць <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да вашых даных, у тым ліку фатаграфій і відэа, на <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Больш не пытацца"</string>
<string name="allow" msgid="7225948811296386551">"Дазволіць"</string>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 4b24a0e43e88..1914bf52bbbb 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Преименуването на документа не бе успешно"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Някои файлове бяха преобразувани"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Да се предостави ли на <xliff:g id="APPNAME"><b>^1</b></xliff:g> достъп до директорията „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ в/ъв <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Да се предостави ли на <xliff:g id="APPNAME"><b>^1</b></xliff:g> достъп до директорията „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Да се предостави ли на <xliff:g id="APPNAME"><b>^1</b></xliff:g> достъп до данните ви в хранилището (<xliff:g id="STORAGE"><i>^2</i></xliff:g>), включително снимки и видеоклипове?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Без повторно питане"</string>
<string name="allow" msgid="7225948811296386551">"Разрешаване"</string>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 79cd38264be8..d931c2b094c2 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"দস্তাবেজের পুনঃনামকরণ ব্যর্থ হয়েছে৷"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"কিছু ফাইল রূপান্তরিত হয়েছে"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> কে <xliff:g id="STORAGE"><i>^3</i></xliff:g> এ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> সংগ্রহ অ্যাক্সেস করার মঞ্জুরি দিতে চান?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> কে <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> সংগ্রহ অ্যাক্সেস করার অনুমতি দেবেন?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> এ থাকা ফটো ও ভিডিওগুলি সমেত <xliff:g id="APPNAME"><b>^1</b></xliff:g> কে আপনার ডেটা অ্যাক্সেস করার অনুমতি দেবেন?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"আর জিজ্ঞাসা করবেন না"</string>
<string name="allow" msgid="7225948811296386551">"অনুমতি দিন"</string>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index 14d6716abd3c..47ff43697c9c 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -118,6 +118,7 @@
<string name="rename_error" msgid="4203041674883412606">"Nije uspjelo preimenovanje dokumenta"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke od datoteka su pretvorene"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Omogućiti <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristup direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> sa <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Odobriti aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristup direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Želite li odobriti aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristup svojim podacima, uključujući fotografije i video zapise, na <xliff:g id="STORAGE"><i>^2</i></xliff:g> ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ne pitaj ponovo"</string>
<string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 73998b17cf1b..09af97d88c7e 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"No s\'ha pogut canviar el nom del document"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"S\'han convertit alguns fitxers"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Vols que l\'aplicació <xliff:g id="APPNAME"><b>^1</b></xliff:g> tingui accés al directori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> de l\'emmagatzematge <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vols que l\'aplicació <xliff:g id="APPNAME"><b>^1</b></xliff:g> tingui accés al directori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vols que l\'aplicació <xliff:g id="APPNAME"><b>^1</b></xliff:g> tingui accés a les dades de <xliff:g id="STORAGE"><i>^2</i></xliff:g>, incloses les fotos i els vídeos?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"No m\'ho demanis més"</string>
<string name="allow" msgid="7225948811296386551">"Permet"</string>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index ffabe77fe98e..cba2e0edb6bd 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Dokument se nepodařilo přejmenovat."</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Některé soubory byly převedeny"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Chcete aplikaci <xliff:g id="APPNAME"><b>^1</b></xliff:g> udělit přístup k adresáři <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> v úložišti <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Chcete aplikaci <xliff:g id="APPNAME"><b>^1</b></xliff:g> udělit přístup k adresáři <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Chcete aplikaci <xliff:g id="APPNAME"><b>^1</b></xliff:g> udělit přístup ke svým datům v úložišti <xliff:g id="STORAGE"><i>^2</i></xliff:g>, včetně fotek a videí?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Příště se neptat"</string>
<string name="allow" msgid="7225948811296386551">"Povolit"</string>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index bf328ab0c8d6..f048e34863d2 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Dokumentet kunne ikke omdøbes"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nogle filer er konverteret"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Vil du give <xliff:g id="APPNAME"><b>^1</b></xliff:g> adgang til mappen <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> på <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vil du give <xliff:g id="APPNAME"><b>^1</b></xliff:g> adgang til indekset <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vil du give <xliff:g id="APPNAME"><b>^1</b></xliff:g> adgang til dine data, herunder billeder og videoer på <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Spørg ikke igen"</string>
<string name="allow" msgid="7225948811296386551">"Tillad"</string>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index 9ccb56490512..a6eae703c198 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Dokument konnte nicht umbenannt werden"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Einige Dateien wurden konvertiert"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> Zugriff auf das Verzeichnis <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> auf <xliff:g id="STORAGE"><i>^3</i></xliff:g> geben?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Möchtest du <xliff:g id="APPNAME"><b>^1</b></xliff:g> Zugriff auf das Verzeichnis <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> geben?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Möchtest du <xliff:g id="APPNAME"><b>^1</b></xliff:g> Zugriff auf deine Daten auf <xliff:g id="STORAGE"><i>^2</i></xliff:g> geben, einschließlich Fotos und Videos?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Nicht mehr fragen"</string>
<string name="allow" msgid="7225948811296386551">"Zulassen"</string>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index f23a35d539d4..7dc20670aed8 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Αποτυχία μετονομασίας εγγράφου"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Ορισμένα αρχεία μετατράπηκαν"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Να εκχωρηθεί στην εφαρμογή <xliff:g id="APPNAME"><b>^1</b></xliff:g> πρόσβαση στον κατάλογο <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> στον αποθηκευτικό χώρο <xliff:g id="STORAGE"><i>^3</i></xliff:g>;"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Εκχώρηση πρόσβασης στην εφαρμογή <xliff:g id="APPNAME"><b>^1</b></xliff:g> στον κατάλογο <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>;"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Θέλετε να εκχωρήσετε πρόσβαση στα δεδομένα σας στην εφαρμογή <xliff:g id="APPNAME"><b>^1</b></xliff:g>, συμπεριλαμβανομένων των φωτογραφιών και των βίντεό σας, στον αποθηκευτικό χώρο <xliff:g id="STORAGE"><i>^2</i></xliff:g>;"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Να μην ερωτηθώ ξανά"</string>
<string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index f82f988afadc..8524de5d67cc 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Don\'t ask again"</string>
<string name="allow" msgid="7225948811296386551">"Allow"</string>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index f82f988afadc..8524de5d67cc 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Don\'t ask again"</string>
<string name="allow" msgid="7225948811296386551">"Allow"</string>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index f82f988afadc..8524de5d67cc 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Don\'t ask again"</string>
<string name="allow" msgid="7225948811296386551">"Allow"</string>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 5c823d0a2661..87641a73c065 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"No se pudo cambiar el nombre del documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se convirtieron algunos archivos"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"¿Otorgar acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> en <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"¿Quieres otorgar acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"¿Quieres otorgar acceso a la app de <xliff:g id="APPNAME"><b>^1</b></xliff:g> a tus datos, incluidas tus fotos y videos en <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"No volver a preguntar"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 60d1d1c91146..9054561c3c45 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Error al cambiar el nombre del documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se han convertido algunos archivos"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"¿Permitir que <xliff:g id="APPNAME"><b>^1</b></xliff:g> acceda al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> (<xliff:g id="STORAGE"><i>^3</i></xliff:g>)?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"¿Permitir que <xliff:g id="APPNAME"><b>^1</b></xliff:g> acceda al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"¿Permitir que <xliff:g id="APPNAME"><b>^1</b></xliff:g> acceda a tus datos, incluidos los vídeos y las fotos, de <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"No volver a preguntar"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 0fdc435c0c4f..4bb2a9b79843 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Dokumendi ümbernimetamine ebaõnnestus"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Mõned failid teisendati"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Kas anda rakendusele <xliff:g id="APPNAME"><b>^1</b></xliff:g> juurdepääs kataloogile <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> salvestusruumis <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Kas anda rakendusele <xliff:g id="APPNAME"><b>^1</b></xliff:g> juurdepääs kataloogile <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Kas anda rakendusele <xliff:g id="APPNAME"><b>^1</b></xliff:g> juurdepääs teie andmetele (sh fotod ja videod) salvestusruumis <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ära enam küsi"</string>
<string name="allow" msgid="7225948811296386551">"Luba"</string>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index b54e542e289e..d2bf89dc4806 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Ezin izan zaio aldatu izena dokumentuari"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Artxibo batzuk bihurtu dira"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> aplikazioari <xliff:g id="STORAGE"><i>^3</i></xliff:g> unitateko <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> direktorioa atzitzeko baimena eman nahi diozu?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> aplikazioari <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> direktoriorako sarbidea eman nahi diozu?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> aplikazioari zure datuak atzitzea baimendu nahi diozu, besteak beste, <xliff:g id="STORAGE"><i>^2</i></xliff:g> biltegian dituzun argazkiak eta bideoak?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ez galdetu berriro"</string>
<string name="allow" msgid="7225948811296386551">"Onartu"</string>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index cc7eeb553da3..1a4c035371dd 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"نام سند تغییر نکرد"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"بعضی از فایل‌ها تبدیل شدند"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"به <xliff:g id="APPNAME"><b>^1</b></xliff:g> اجازه داده شود به فهرست راهنمای <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> در <xliff:g id="STORAGE"><i>^3</i></xliff:g> دسترسی داشته باشد؟"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"به <xliff:g id="APPNAME"><b>^1</b></xliff:g> اجازه دسترسی به دایرکتوری <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> داده شود؟"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"به <xliff:g id="APPNAME"><b>^1</b></xliff:g> اجازه می‌دهید به داده‌هایتان دسترسی پیدا کند، از جمله عکس‌ها و ویدیوهایتان در <xliff:g id="STORAGE"><i>^2</i></xliff:g>؟"</string>
<string name="never_ask_again" msgid="4295278542972859268">"دوباره سؤال نشود"</string>
<string name="allow" msgid="7225948811296386551">"ارزیابی‌شده"</string>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 17e4d759c6b0..dfcfe89f384e 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Dokumentin nimen muuttaminen epäonnistui."</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Joitakin tiedostoja muunnettiin."</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Myönnetäänkö sovellukselle <xliff:g id="APPNAME"><b>^1</b></xliff:g> sijainnissa <xliff:g id="STORAGE"><i>^3</i></xliff:g> olevan hakemiston <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> käyttöoikeus?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Saako <xliff:g id="APPNAME"><b>^1</b></xliff:g> käyttää hakemistoa <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Myönnetäänkö sovellukselle <xliff:g id="APPNAME"><b>^1</b></xliff:g> sijainnissa <xliff:g id="STORAGE"><i>^2</i></xliff:g> olevien tietojesi, mukaan lukien valokuviesi ja videoidesi, käyttöoikeus?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Älä kysy uudestaan"</string>
<string name="allow" msgid="7225948811296386551">"Salli"</string>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 5dbf5ebe2295..543e2260cff3 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Impossible de renommer le document"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Accorder à <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accès au répertoire <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> sur <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Accorder à <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accès au répertoire <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Voulez-vous accorder l\'accès à vos données à <xliff:g id="APPNAME"><b>^1</b></xliff:g>, y compris vos photos et vos vidéos, sur <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ne plus me demander"</string>
<string name="allow" msgid="7225948811296386551">"Autoriser"</string>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 127d0da93f46..05716d7f4587 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Échec du changement de nom du document."</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Autoriser <xliff:g id="APPNAME"><b>^1</b></xliff:g> à accéder à l\'annuaire \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\" sur <xliff:g id="STORAGE"><i>^3</i></xliff:g> ?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Autoriser <xliff:g id="APPNAME"><b>^1</b></xliff:g> à accéder à l\'annuaire \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\" ?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Autoriser <xliff:g id="APPNAME"><b>^1</b></xliff:g> à accéder à vos données, y compris les photos et les vidéos, sur <xliff:g id="STORAGE"><i>^2</i></xliff:g> ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ne plus demander"</string>
<string name="allow" msgid="7225948811296386551">"Autoriser"</string>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index 4cce3c96e16a..5797a9600eea 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Non se puido cambiar o nome do documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Convertéronse algúns ficheiros"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Queres outorgar acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no almacenamento de <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Queres darlle acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Queres darlle acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> aos teus datos almacenados en <xliff:g id="STORAGE"><i>^2</i></xliff:g>, incluídos vídeos e fotos?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Non preguntar de novo"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 1db54f94c29a..48e43c492023 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"દસ્તાવેજનું નામ બદલવામાં નિષ્ફળ થયાં"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"કેટલીક ફાઇલો રૂપાંતરિત કરી હતી"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="STORAGE"><i>^3</i></xliff:g> પર <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> નિર્દેશિકાની ઍક્સેસ આપીએ?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> નિર્દેશિકાની ઍક્સેસ આપીએ?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="STORAGE"><i>^2</i></xliff:g> પર ફોટા અને વિડિઓઝ સહિત તમારા ડેટાની અ‍ૅક્સેસ આપીએ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"ફરીથી પૂછશો નહીં"</string>
<string name="allow" msgid="7225948811296386551">"મંજૂરી આપો"</string>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index de1e25e568ef..fa82ee8d13e3 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"दस्‍तावेज़ का नाम बदलना विफल रहा"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"कुछ फ़ाइलें रूपांतरित हो गई थीं"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^3</i></xliff:g> पर <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिका का एक्सेस दें?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिका का एक्सेस प्रदान करें?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^2</i></xliff:g> पर मौजूद फ़ोटो और वीडियो सहित, अपने डेटा का एक्सेस प्रदान करें?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"फिर से ना पूछें"</string>
<string name="allow" msgid="7225948811296386551">"अनुमति दें"</string>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index bf91c6a5a402..7988c719cf51 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -118,6 +118,7 @@
<string name="rename_error" msgid="4203041674883412606">"Naziv dokumenta nije promijenjen"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke su datoteke konvertirane"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Želite li aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> odobriti pristup direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> na pohrani <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Želite li aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> odobriti da pristupa direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Želite li aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dopustiti pristup podacima, uključujući fotografije i videozapise na vanjskoj pohrani (<xliff:g id="STORAGE"><i>^2</i></xliff:g>)?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Više me ne pitaj"</string>
<string name="allow" msgid="7225948811296386551">"Dopusti"</string>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index f9553189820c..fb666b51088b 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Nem sikerült átnevezni a dokumentumot"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Egyes fájlokat konvertált a rendszer"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Hozzáférést biztosít a(z) <xliff:g id="APPNAME"><b>^1</b></xliff:g> számára a(z) <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> könyvtárhoz itt: <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Hozzáférést biztosít a(z) <xliff:g id="APPNAME"><b>^1</b></xliff:g> alkalmazásnak a(z) <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> könyvtárhoz?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Hozzáférést biztosít a(z) <xliff:g id="APPNAME"><b>^1</b></xliff:g> számára az Ön adataihoz, beleértve a következő tárhelyen található képekhez és videókhoz: <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ne jelenjen meg többé"</string>
<string name="allow" msgid="7225948811296386551">"Engedélyezés"</string>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index b1af92c1f4eb..f6c3ad5aa55e 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Չհաջողվեց վերանվանել փաստաթուղթը"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Որոշ ֆայլեր փոխարկվել են"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> հավելվածին տրամադրե՞լ <xliff:g id="STORAGE"><i>^3</i></xliff:g>-ի <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> գրացուցակն օգտագործելու թույլտվություն:"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> հավելվածին տրամադրե՞լ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> գրացուցակն օգտագործելու թույլտվություն:"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> հավելվածին տրամադրե՞լ <xliff:g id="STORAGE"><i>^2</i></xliff:g>-ում պահվող ձեր տվյալները, այդ թվում նաև լուսանկարները և տեսանյութերը, օգտագործելու թույլտվություն:"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Այլևս չհարցնել"</string>
<string name="allow" msgid="7225948811296386551">"Թույլատրել"</string>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 87576fb3946e..a8aee5297462 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Gagal mengganti nama dokumen"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Beberapa file dikonversi"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses ke direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> di <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses ke direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses ke data Anda, termasuk foto dan video, di <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Jangan tanya lagi"</string>
<string name="allow" msgid="7225948811296386551">"Izinkan"</string>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index d3be73a04ec9..88aaced592e4 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Ekki tókst að endurnefna skjalið"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sumum skrám var umbreytt"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Veita <xliff:g id="APPNAME"><b>^1</b></xliff:g> aðgang að skráasafninu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> á <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Viltu veita <xliff:g id="APPNAME"><b>^1</b></xliff:g> aðgang að skráasafninu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Veita <xliff:g id="APPNAME"><b>^1</b></xliff:g> aðgang að gögnunum þínum, þar á meðal myndum og myndskeiðum, á <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ekki spyrja aftur"</string>
<string name="allow" msgid="7225948811296386551">"Leyfa"</string>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 736d31c1530b..b7497dbd4f99 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Ridenominazione documento non riuscita"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alcuni file sono stati convertiti"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Concedere all\'app <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accesso alla directory <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> su <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Concedere all\'app <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accesso alla directory <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Concedere all\'app <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accesso ai tuoi dati, inclusi video e foto, sull\'unità <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Non chiedermelo più"</string>
<string name="allow" msgid="7225948811296386551">"Consenti"</string>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 2446a4b81ef4..4498f8c01dec 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"ניסיון שינוי שם המסמך נכשל"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"קבצים מסוימים הומרו"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"האם להעניק לאפליקציה <xliff:g id="APPNAME"><b>^1</b></xliff:g> גישה לספריה <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> באחסון <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"האם להעניק לאפליקציה <xliff:g id="APPNAME"><b>^1</b></xliff:g> גישה אל ספריית <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"האם להעניק לאפליקציה <xliff:g id="APPNAME"><b>^1</b></xliff:g> גישה לנתונים שלך, כולל תמונות וסרטונים, השמורים ב<xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"אל תשאל שוב"</string>
<string name="allow" msgid="7225948811296386551">"אפשר"</string>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index dc39b999f8dd..bfb1c3a040c1 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ドキュメントの名前を変更できませんでした"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"一部のファイルが変換されました"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"「<xliff:g id="STORAGE"><i>^3</i></xliff:g>」の「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」ディレクトリに「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」へのアクセスを許可しますか?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」アプリに「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」ディレクトリへのアクセスを許可しますか?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g>の写真や動画などのデータへのアクセスを「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」に許可しますか?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"今後表示しない"</string>
<string name="allow" msgid="7225948811296386551">"許可"</string>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 0af8dd93ec3a..f0e9e86f5a63 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"დოკუმენტის გადარქმევა ვერ მოხერხდა"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ზოგიერთი ფაილი გარდაქმნილია"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"გსურთ, <xliff:g id="APPNAME"><b>^1</b></xliff:g> სარგებლობდეს <xliff:g id="STORAGE"><i>^3</i></xliff:g>-ის დირექტორიაზე „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ წვდომის უფლებით?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"გსურთ, <xliff:g id="APPNAME"><b>^1</b></xliff:g> სარგებლობდეს დირექტორიაზე „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ წვდომის უფლებით?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"გსურთ, <xliff:g id="APPNAME"><b>^1</b></xliff:g> სარგებლობდეს <xliff:g id="STORAGE"><i>^2</i></xliff:g>-ზე არსებულ მონაცემებზე, მათ შორის, ფოტოებსა და ვიდეოებზე, წვდომის უფლებით?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"აღარ მკითხოთ"</string>
<string name="allow" msgid="7225948811296386551">"უფლების მიცემა"</string>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index 3d6b758ace83..26879000713f 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Құжат қайта аталмады"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> қолданбасына <xliff:g id="STORAGE"><i>^3</i></xliff:g> қоймасындағы <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогына өтуге рұқсат беру керек пе?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> қолданбасына <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогына қатынас беру керек пе?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> <xliff:g id="STORAGE"><i>^2</i></xliff:g> қоймасындағы деректерге, соның ішінде фотосуреттерге және бейнелерге кіру мүмкіндігін беру керек пе?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Қайта сұралмасын"</string>
<string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 0eb13961858e..ea240432260a 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"បានបរាជ័យក្នុងការប្តូរឈ្មោះឯកសារ"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ឯកសារមួយចំនួនត្រូវបានបម្លែង"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"ផ្តល់សិទ្ធិឲ្យ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ចូលដំណើរការថត <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> នៅលើ <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ផ្តល់សិទ្ធិឲ្យ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ចូលដំណើរការថត <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ឬ?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"ផ្តល់សិទ្ធិអនុញ្ញាតដល់ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ដើម្បីចូលដំណើរការទិន្នន័យរបស់អ្នក រាប់បញ្ចូលទាំងរូបថត និងវីដេអូ នៅលើ <xliff:g id="STORAGE"><i>^2</i></xliff:g> ឬទេ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"កុំសួរទៀត"</string>
<string name="allow" msgid="7225948811296386551">"អនុញ្ញាត​"</string>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index a5a8ab2c51f3..c756009faabd 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ಡಾಕ್ಯುಮೆಂಟ್ ಮರುಹೆಸರಿಸಲು ವಿಫಲವಾಗಿದೆ"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ಕೆಲವು ಫೈಲ್‌ಗಳನ್ನು ಪರಿವರ್ತಿಸಲಾಗಿದೆ"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> ರಲ್ಲಿ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ಡೈರೆಕ್ಟರಿಗೆ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ಪ್ರವೇಶ ನೀಡುವುದೇ?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g><xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ಡೈರೆಕ್ಟರಿ ಪ್ರವೇಶಿಸಲು ಅನುಮತಿಸುವುದೇ?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> ಸಂಗ್ರಹಣೆಯಲ್ಲಿನ ಪೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APPNAME"><b>^1</b></xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುವುದೇ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"ಮತ್ತೆ ಕೇಳಬೇಡಿ"</string>
<string name="allow" msgid="7225948811296386551">"ಅನುಮತಿಸು"</string>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 9975ce0646e8..4d5dcf979a8c 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"문서 이름을 변경하지 못했습니다."</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"일부 파일이 변환되었습니다."</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>이(가) <xliff:g id="STORAGE"><i>^3</i></xliff:g>에서 <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> 디렉토리에 액세스하도록 허용하시겠습니까?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>이(가) <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> 디렉토리에 액세스하도록 허용하시겠습니까?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>에서 사진, 동영상 등 <xliff:g id="STORAGE"><i>^2</i></xliff:g>의 내 데이터에 액세스하도록 허용하시겠습니까?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"다시 묻지 않음"</string>
<string name="allow" msgid="7225948811296386551">"허용"</string>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index be2aca8b90fc..1b39039e6f29 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Документтин аталышы өзгөртүлбөй калды"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Айрым файлдардын форматы өзгөртүлдү"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> колдонмосуна <xliff:g id="STORAGE"><i>^3</i></xliff:g> түзмөгүндөгү <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> папканы пайдалануу мүмкүнчүлүгү берилсинби?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> колдонмосуна <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогун пайдалануу мүмкүнчүлүгү берилсинби?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> колдонмосуна <xliff:g id="STORAGE"><i>^2</i></xliff:g> түзмөгүндөгү дайындарыңыз, сүрөттөрүңүз жана видеолоруңузду пайдалануу мүмкүнчүлүгү берилсинби?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Экинчи суралбасын"</string>
<string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string>
@@ -130,7 +131,7 @@
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> куржун мазмуну менен жок кылынсынбы?</item>
</plurals>
<plurals name="delete_items_confirmation_message" formatted="false" msgid="5376214433530243459">
- <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> нерсе жок кылынчынбы?</item>
- <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> нерсе жок кылынчынбы?</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> нерсе жок кылынсынбы?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> нерсе жок кылынсынбы?</item>
</plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index ed9646416e2a..a4f381db5e5d 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ປ່ຽນຊື່ເອກະສານບໍ່ສຳເລັດ"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ປ່ຽນແປງບາງໄຟລ໌ແລ້ວ"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"ອະນຸຍາດສິດເຂົ້າເຖິງໃຫ້ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ເພື່ອເຂົ້າໄດເຣກທໍຣີ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ຢູ່ <xliff:g id="STORAGE"><i>^3</i></xliff:g> ບໍ?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ອະນຸມັດ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ໃຫ້ເຂົ້າຫາໄດເຣັກທໍຣີ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ບໍ?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"ອະນຸມັດໃຫ້ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ເຂົ້າເຖິງຂໍ້ມູນຂອງທ່ານ ເຊິ່ງຮວມເຖິງຮູບພາບ ແລະ ວິດີໂອໃນ <xliff:g id="STORAGE"><i>^2</i></xliff:g> ໄດ້ບໍ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"ບໍ່ຕ້ອງຖາມຄືນ"</string>
<string name="allow" msgid="7225948811296386551">"ອະນຸຍາດ"</string>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 0e95ea00abf9..2e0df93dfaeb 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Nepavyko pervardyti dokumento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Kai kurie failai buvo konvertuoti"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Suteikti „<xliff:g id="APPNAME"><b>^1</b></xliff:g>“ prieigą prie katalogo „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Suteikti „<xliff:g id="APPNAME"><b>^1</b></xliff:g>“ prieigą prie katalogo „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Suteikti programai „<xliff:g id="APPNAME"><b>^1</b></xliff:g>“ prieigą prie duomenų, įskaitant nuotraukas ir vaizdo įrašus, <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Daugiau neklausti"</string>
<string name="allow" msgid="7225948811296386551">"Leisti"</string>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 9f39f2edd61b..fb81aa002e9f 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -118,6 +118,7 @@
<string name="rename_error" msgid="4203041674883412606">"Neizdevās pārdēvēt dokumentu"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Daži faili tika pārveidoti."</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Vai atļaut lietotnei <xliff:g id="APPNAME"><b>^1</b></xliff:g> piekļūt direktorijam <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> šajā krātuvē: <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vai piešķirt lietotnei <xliff:g id="APPNAME"><b>^1</b></xliff:g> piekļuvi direktorijam <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vai atļaut lietotnei <xliff:g id="APPNAME"><b>^1</b></xliff:g> piekļūt jūsu datiem, tostarp fotoattēliem un videoklipiem, šajā krātuvē: <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Turpmāk vairs nejautāt"</string>
<string name="allow" msgid="7225948811296386551">"Atļaut"</string>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index bc3b7fa7dd38..ad428a0696ec 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Не успеа да се преименува документот"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некои датотеки беа конвертирани"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Овозможете пристап на <xliff:g id="APPNAME"><b>^1</b></xliff:g> до директориумот <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> на <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Овозможете пристап на <xliff:g id="APPNAME"><b>^1</b></xliff:g> до директориумот <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Да се овозможи пристап на <xliff:g id="APPNAME"><b>^1</b></xliff:g> до вашите податоци, вклучувајќи фотографии и видеа, на <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Не прашувај повторно"</string>
<string name="allow" msgid="7225948811296386551">"Дозволи"</string>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index 9a7509f65071..5a1651260779 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ഡോക്യുമെന്റിന്റെ പേരുമാറ്റുന്നത് പരാജയപ്പെട്ടു"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ചില ഫയലുകൾ പരിവർത്തനം ചെയ്യപ്പെട്ടു"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> സ്റ്റോറേജിലെ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> എന്ന ഡയറക്റ്ററിയിലേക്ക് <xliff:g id="APPNAME"><b>^1</b></xliff:g> ആപ്പിന് ആക്സസ് അനുവദിക്കണോ?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> എന്ന ഡയറക്ടറിയിലേക്ക് <xliff:g id="APPNAME"><b>^1</b></xliff:g> ആപ്പിന് ആക്സസ് അനുവദിക്കണോ?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> സ്റ്റോറേജിലെ ഫോട്ടോകളും വീഡിയോകളും ഉൾപ്പെടെ, നിങ്ങളുടെ ഡാറ്റയിലേക്ക് <xliff:g id="APPNAME"><b>^1</b></xliff:g> ആപ്പിന് ആക്സസ്സ് അനുവദിക്കണോ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"വീണ്ടും ആവശ്യപ്പെടരുത്"</string>
<string name="allow" msgid="7225948811296386551">"അനുവദിക്കുക"</string>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index f424f8ea6f86..cf2c2d47f356 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Баримт бичгийн нэрийн өөрчилж чадсангүй"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Зарим файлыг хөрвүүлсэн"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g>-д байгаа <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> лавлагаанд хандахыг <xliff:g id="APPNAME"><b>^1</b></xliff:g>-д зөвшөөрөх үү?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> лавлагаанд хандах эрхийг <xliff:g id="APPNAME"><b>^1</b></xliff:g>-д олгох уу?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g>-д байгаа зураг, видео гэх мэт таны өгөгдөлд <xliff:g id="APPNAME"><b>^1</b></xliff:g> хандахыг зөвшөөрөх үү?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Дахин бүү асуу"</string>
<string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 556c1e620e74..09dd1334cb5c 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"दस्तऐवज पुनर्नामित करण्‍यात अयशस्वी झाले"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"काही फायली रूपांतरित केल्या होत्या"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> वर <xliff:g id="APPNAME"><b>^1</b></xliff:g> ला <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकेवर प्रवेशाची मंजूरी द्यायची?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ला <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकमध्ये प्रवेश मंजूर करायचा?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ला <xliff:g id="STORAGE"><i>^2</i></xliff:g> वर फोटो आणि व्हिडिओंसह, आपल्या डेटामध्ये प्रवेश करण्याची मंजूरी द्यायची?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"पुन्हा विचारू नका"</string>
<string name="allow" msgid="7225948811296386551">"अनुमती द्या"</string>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 0f2af2f75190..9eb3d49720f5 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Gagal menamakan semula dokumen"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sesetengah fail telah ditukarkan"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses kepada direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> di <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses kepada direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses kepada data anda, termasuk foto dan video pada <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Jangan tanya lagi"</string>
<string name="allow" msgid="7225948811296386551">"Benarkan"</string>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 6acbc806a747..7c637c4cfd74 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"စာရွက်စာတမ်းကို အမည်ပြောင်းခြင်း မအောင်မြင်ပါ"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"အချို့ဖိုင်များကို ပြောင်းလဲထားသည်"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ကို <xliff:g id="STORAGE"><i>^3</i></xliff:g> ရှိ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> လမ်းညွှန်အား အသုံးပြုခွင့်ပေးမလား။"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> အား <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> စာရင်းကို အသုံးပြုခွင့်ပေးမလား။"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> ရှိဓာတ်ပုံများနှင့် ဗီဒီယိုများအပါအဝင် သင့်ဒေတာများကို <xliff:g id="APPNAME"><b>^1</b></xliff:g> အားအသုံးပြုခွင့်ပေးမလား။"</string>
<string name="never_ask_again" msgid="4295278542972859268">"နောက်ထပ်မမေးပါနှင့်"</string>
<string name="allow" msgid="7225948811296386551">"ခွင့်ပြုသည်"</string>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index c2c983e1ee76..3c344eb14be9 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Kunne ikke gi dokumentet nytt navn"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Noen filer er konvertert"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Vil du gi <xliff:g id="APPNAME"><b>^1</b></xliff:g> tilgang til <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-katalogen på <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vil du gi <xliff:g id="APPNAME"><b>^1</b></xliff:g> tilgang til <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-katalogen?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vil du gi <xliff:g id="APPNAME"><b>^1</b></xliff:g> tilgang til dataene dine – inkludert bilder og videoer – på <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ikke spør igjen"</string>
<string name="allow" msgid="7225948811296386551">"Tillat"</string>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 31c4c2c30fed..9fef037a10c9 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"कागजात पुन: नामाकरण गर्न असफल भयो"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"केही फाइलहरू परिवर्तन गरिएका थिए"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> लाई <xliff:g id="STORAGE"><i>^3</i></xliff:g> मा भएको <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकामा पहुँच गर्न अनुमति दिने हो?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> लाई <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकामाथि पहुँच गर्न अनुमति प्रदान गर्ने हो?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> लाई <xliff:g id="STORAGE"><i>^2</i></xliff:g> मा भएका तस्बिर र भिडियोहरू लगायत तपाईँको डेटामा पहुँच गर्नका लागि अनुमति दिने हो?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"फेरि नसोध्नुहोस्"</string>
<string name="allow" msgid="7225948811296386551">"अनुमति दिनुहोस्"</string>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index 385b5079ff2c..c5b9d76899b1 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Kan naam van document niet wijzigen"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige bestanden zijn geconverteerd"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang verlenen tot de map <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> op <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang verlenen tot de map <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang verlenen tot je gegevens, waaronder foto\'s en video\'s, op <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Niet meer vragen"</string>
<string name="allow" msgid="7225948811296386551">"Toestaan"</string>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 7603f5879c22..7d5e14a75d90 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ਦਸਤਾਵੇਜ਼ ਦਾ ਮੁੜ-ਨਾਮਕਰਨ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ਕੁਝ ਫ਼ਾਈਲਾਂ ਤਬਦੀਲ ਕੀਤੀਆਂ ਗਈਆਂ ਸਨ"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="STORAGE"><i>^3</i></xliff:g> \'ਤੇ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ਡਾਇਰੈਕਟਰੀ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ਡਾਇਰੈਕਟਰੀ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="STORAGE"><i>^2</i></xliff:g> \'ਤੇ ਫੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਸਮੇਤ, ਤੁਹਾਡੇ ਡੈਟੇ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
<string name="allow" msgid="7225948811296386551">"ਆਗਿਆ ਦਿਓ"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index b234a9ec8605..ca007d7f858e 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Nie udało się zmienić nazwy dokumentu"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektóre pliki zostały przekonwertowane"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Zezwolić aplikacji <xliff:g id="APPNAME"><b>^1</b></xliff:g> na dostęp do katalogu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> w pamięci masowej <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Przyznać aplikacji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dostęp do katalogu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Zezwolić aplikacji <xliff:g id="APPNAME"><b>^1</b></xliff:g> na dostęp do Twoich danych, w tym zdjęć i filmów, zapisanych w pamięci <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Nie pytaj ponownie"</string>
<string name="allow" msgid="7225948811296386551">"Zezwól"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 634ac963dec4..21359c7dbca1 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Conceder ao <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no/na <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 54408015ee68..aea1249ab353 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Falha ao mudar o nome do documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns ficheiros foram convertidos"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no(a) <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no(a) <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 634ac963dec4..21359c7dbca1 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Conceder ao <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no/na <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 3dc93ef92cc3..4b833b18a24c 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -118,6 +118,7 @@
<string name="rename_error" msgid="4203041674883412606">"Documentul nu a putut fi redenumit"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Unele fișiere au fost convertite"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Permiteți aplicației <xliff:g id="APPNAME"><b>^1</b></xliff:g> accesul la directorul <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> de pe <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Permiteți aplicației <xliff:g id="APPNAME"><b>^1</b></xliff:g> să acceseze directorul <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Permiteți aplicației <xliff:g id="APPNAME"><b>^1</b></xliff:g> să vă acceseze datele, inclusiv fotografiile și videoclipurile, de pe <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Nu mai întreba"</string>
<string name="allow" msgid="7225948811296386551">"Permiteți"</string>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index fef3015d830e..6ba635d7aadc 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Не удалось переименовать документ"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Формат некоторых файлов изменен"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Открыть приложению \"<xliff:g id="APPNAME"><b>^1</b></xliff:g>\" доступ к папке \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\" на устройстве \"<xliff:g id="STORAGE"><i>^3</i></xliff:g>\"?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Открыть приложению \"<xliff:g id="APPNAME"><b>^1</b></xliff:g>\" доступ к папке \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\"?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Открыть приложению \"<xliff:g id="APPNAME"><b>^1</b></xliff:g>\" доступ к вашим данным, включая фото и видео, на носителе: <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Больше не спрашивать"</string>
<string name="allow" msgid="7225948811296386551">"Разрешить"</string>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index d49c2f37032f..41c9d4a87704 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ලේඛනය යළි නම් කිරීම අසාර්ථක විය"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"සමහර ගොනු පරිවර්තනය කරන ලදී"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> හට <xliff:g id="STORAGE"><i>^3</i></xliff:g> මත <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> නාමාවලිය වෙත ප්‍රවේශය දෙන්නද?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ප්‍රවේශය <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> නාමාවලිය වෙත ලබා දෙන්නද?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> හි, ඡායාරූප සහ වීඩියෝ ඇතුළුව, ඔබේ දත්තවලට <xliff:g id="APPNAME"><b>^1</b></xliff:g> හට ප්‍රවේශය ලබා දෙන්නද?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"නැවත අසන්න එපා"</string>
<string name="allow" msgid="7225948811296386551">"අවසර දෙන්න"</string>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index bd75175c487c..1ff01b054d23 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Premenovanie dokumentu zlyhalo"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektoré súbory boli konvertované"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Udeliť aplikácii <xliff:g id="APPNAME"><b>^1</b></xliff:g> prístup k adresáru <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> v úložisku <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Udeliť aplikácii <xliff:g id="APPNAME"><b>^1</b></xliff:g> prístup k adresáru <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Chcete aplikácii <xliff:g id="APPNAME"><b>^1</b></xliff:g> udeliť prístup k dátam (vrátane fotiek a videí) v úložisku <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Nabudúce sa nepýtať"</string>
<string name="allow" msgid="7225948811296386551">"Povoliť"</string>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index 78ec8fed5321..d8b983cc7bdb 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Dokumenta ni bilo mogoče preimenovati"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nekatere datoteke so bile pretvorjene"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Želite aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dovoliti dostop do imenika <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> v shrambi <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Želite aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dovoliti dostop do imenika <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Odobrite aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dostop do podatkov, vključno s fotografijami in videoposnetki, v shrambi <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ne sprašuj več"</string>
<string name="allow" msgid="7225948811296386551">"Dovoli"</string>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 662e7f09f1cd..933a537f20cc 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Riemërtimi i dokumentit dështoi"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Disa skedarë u konvertuan"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Jepi aplikacionit <xliff:g id="APPNAME"><b>^1</b></xliff:g> qasje te direktoria <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> në <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"T\'i jepet aplikacionit <xliff:g id="APPNAME"><b>^1</b></xliff:g> qasje te direktoria <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"T\'i jepet aplikacionit <xliff:g id="APPNAME"><b>^1</b></xliff:g> qasje te të dhënat, duke përfshirë fotografitë dhe videot, në <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Mos pyet përsëri"</string>
<string name="allow" msgid="7225948811296386551">"Lejo"</string>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index 690f81cc8581..0505f423c1b0 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -118,6 +118,7 @@
<string name="rename_error" msgid="4203041674883412606">"Преименовање документа није успело"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Неке датотеке су конвертоване"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Желите ли да апликацији <xliff:g id="APPNAME"><b>^1</b></xliff:g> одобрите приступ директоријуму <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> на меморијском простору <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Желите да дозволите да <xliff:g id="APPNAME"><b>^1</b></xliff:g> приступа директоријуму <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Желите да ли да дозволите да апликација <xliff:g id="APPNAME"><b>^1</b></xliff:g> приступа подацима, укључујући слике и видео снимке, на локацији <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Не питај поново"</string>
<string name="allow" msgid="7225948811296386551">"Дозволи"</string>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 18497828a7ed..99f334b4f473 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Det gick inte att byta namn på dokumentet"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Vissa filer konverterades"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Vill du ge <xliff:g id="APPNAME"><b>^1</b></xliff:g> åtkomst till katalogen <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> på <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vill du ge <xliff:g id="APPNAME"><b>^1</b></xliff:g> åtkomst till katalogen <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vill du ge <xliff:g id="APPNAME"><b>^1</b></xliff:g> åtkomst till din data (inklusive foton och videor) på <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Fråga inte igen"</string>
<string name="allow" msgid="7225948811296386551">"Tillåt"</string>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index bf4b744a9204..566e6a462fef 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Imeshindwa kubadilisha jina la hati"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Baadhi ya faili zimebadilishwa muundo"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Ungependa kuruhusu <xliff:g id="APPNAME"><b>^1</b></xliff:g> ifikie saraka ya <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> kwenye <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Ungependa kuruhusu <xliff:g id="APPNAME"><b>^1</b></xliff:g> ifikie saraka ya <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Ungependa kuruhusu <xliff:g id="APPNAME"><b>^1</b></xliff:g> ifikie data yako, ikiwa ni pamoja na picha na video kwenye <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Usiniulize tena"</string>
<string name="allow" msgid="7225948811296386551">"Ruhusu"</string>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 43d29e22afdf..9a8b4ec71118 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ஆவணத்திற்கு மறுபெயரிடுவதில் தோல்வி"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"சில கோப்புகள் மாற்றப்பட்டன"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> இல் உள்ள <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> கோப்பகத்தை அணுக <xliff:g id="APPNAME"><b>^1</b></xliff:g>ஐ அனுமதிக்கவா?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> கோப்பகத்தை அணுக, <xliff:g id="APPNAME"><b>^1</b></xliff:g>ஐ அனுமதிக்கவா?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> இல் உள்ள படங்கள், வீடியோக்கள் உட்பட எல்லா தரவையும் அணுக, <xliff:g id="APPNAME"><b>^1</b></xliff:g>ஐ அனுமதிக்கவா?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"மீண்டும் கேட்காதே"</string>
<string name="allow" msgid="7225948811296386551">"அனுமதி"</string>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index c9233eca7d05..224d0db288eb 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"పత్రం పేరు మార్చడంలో విఫలమైంది"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"కొన్ని పైల్‌లు మార్చబడ్డాయి"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>కి <xliff:g id="STORAGE"><i>^3</i></xliff:g>లో <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> డైరెక్టరీ ప్రాప్యతను మంజూరు చేయాలా?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>కి <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> డైరెక్టరీ ప్రాప్యతను మంజూరు చేయాలా?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g>లో ఫోటోలు మరియు వీడియోలతో సహా మీ డేటా ప్రాప్యతను <xliff:g id="APPNAME"><b>^1</b></xliff:g>కి మంజూరు చేయాలా?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"మళ్లీ అడగవద్దు"</string>
<string name="allow" msgid="7225948811296386551">"అనుమతించండి"</string>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 491e984c7e2c..af07584d48eb 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"ไม่สามารถเปลี่ยนชื่อเอกสาร"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"แปลงบางไฟล์แล้ว"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"ให้สิทธิ์ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ในการเข้าถึงไดเรกทอรี <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ใน <xliff:g id="STORAGE"><i>^3</i></xliff:g> ไหม"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ให้สิทธิ์ <xliff:g id="APPNAME"><b>^1</b></xliff:g> เข้าถึงไดเรกทอรี <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ไหม"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"ให้สิทธิ์ <xliff:g id="APPNAME"><b>^1</b></xliff:g> เข้าถึงข้อมูลของคุณ รวมถึงรูปภาพและวิดีโอใน <xliff:g id="STORAGE"><i>^2</i></xliff:g> ไหม"</string>
<string name="never_ask_again" msgid="4295278542972859268">"ไม่ต้องถามอีก"</string>
<string name="allow" msgid="7225948811296386551">"อนุญาต"</string>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index 27d667108be3..b2acf05459cc 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Hindi napalitan ang pangalan ng dokumento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Na-convert ang ilang file"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Bigyan ang <xliff:g id="APPNAME"><b>^1</b></xliff:g> ng access sa directory ng <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> sa <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Bibigyan ang <xliff:g id="APPNAME"><b>^1</b></xliff:g> ng access sa direktoryong <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Bigyan ang <xliff:g id="APPNAME"><b>^1</b></xliff:g> ng access sa iyong data, kabilang ang mga larawan at video, sa <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Huwag nang tatanunging muli"</string>
<string name="allow" msgid="7225948811296386551">"Payagan"</string>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index dda9f28d99ec..c5653c9ffe31 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Dokümanın adı değiştirilemedi"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bazı dosyalar dönüştürüldü"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> uygulamasına <xliff:g id="STORAGE"><i>^3</i></xliff:g> depolama alanındaki <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> dizinine erişim izni verilsin mi?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> dizinine erişmek için <xliff:g id="APPNAME"><b>^1</b></xliff:g> uygulamasına izin verilsin mi?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> uygulamasının, fotoğraflar ve videolar dahil olmak üzere <xliff:g id="STORAGE"><i>^2</i></xliff:g> üzerindeki verilerinize erişmesine izin verilsin mi?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Tekrar sorma"</string>
<string name="allow" msgid="7225948811296386551">"İzin Ver"</string>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index ec7e1d60c317..21532b675437 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -125,6 +125,7 @@
<string name="rename_error" msgid="4203041674883412606">"Не вдалося перейменувати документ"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Деякі файли конвертовано"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Надати додатку <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ до каталогу <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> на пристрої пам’яті <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Надати додатку <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ до каталогу \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\"?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Надати додатку <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ до ваших даних, зокрема до фотографій і відео, які містить <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Не запитувати знову"</string>
<string name="allow" msgid="7225948811296386551">"Дозвол."</string>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 4ea998526124..eb0cfc8e7b54 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"دستاویز کا نام تبدیل کرنے میں ناکام"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"کچھ فائلوں کو تبدیل کیا گیا تھا"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> کو <xliff:g id="STORAGE"><i>^3</i></xliff:g> پر <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ڈائرکٹری تک رسائی عطا کریں؟"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> کو <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ڈائرکٹری تک رسائی دیں؟"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> کو اپنے ڈیٹا بشمول <xliff:g id="STORAGE"><i>^2</i></xliff:g> پر موجود تصاویر اور ویڈیوز تک رسائی عطا کریں؟"</string>
<string name="never_ask_again" msgid="4295278542972859268">"دوبارہ نہ پوچھیں"</string>
<string name="allow" msgid="7225948811296386551">"اجازت دیں"</string>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index dffbba5e359c..2654308970b7 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -110,7 +110,8 @@
<string name="menu_rename" msgid="7678802479104285353">"Qayta nomlash"</string>
<string name="rename_error" msgid="4203041674883412606">"Hujjatni qayta nomlab bo‘lmadi"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bir nechta fayllar o‘girildi"</string>
- <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasining <xliff:g id="STORAGE"><i>^3</i></xliff:g> xotirasidagi “<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>” jildiga kirishiga ruxsat berilsinmi?"</string>
+ <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasiga <xliff:g id="STORAGE"><i>^3</i></xliff:g> xotirasidagi “<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>” jildidan foydalanishiga ruxsat berilsinmi?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasiga “<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>” jildidan foydalanishiga ruxsat berilsinmi?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasiga <xliff:g id="STORAGE"><i>^2</i></xliff:g> xotirasidagi ma’lumotlardan, jumladan, rasmlar va videolardan foydalanishiga ruxsat berilsinmi?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Boshqa so‘ralmasin"</string>
<string name="allow" msgid="7225948811296386551">"Ruxsat berish"</string>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 127c2d322575..9af7db08cf8c 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Không đổi được tên tài liệu"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Đã chuyển đổi một số tệp"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Cấp cho <xliff:g id="APPNAME"><b>^1</b></xliff:g> quyền truy cập vào thư mục <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> trong <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Cấp cho <xliff:g id="APPNAME"><b>^1</b></xliff:g> quyền truy cập thư mục <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Cấp cho <xliff:g id="APPNAME"><b>^1</b></xliff:g> quyền truy cập vào dữ liệu của bạn, kể cả ảnh và video trên <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Không hỏi lại"</string>
<string name="allow" msgid="7225948811296386551">"Cho phép"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 45d22a303aab..e3db1a07749a 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"无法重命名文档"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问 <xliff:g id="STORAGE"><i>^3</i></xliff:g>上的“<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>”目录吗?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>目录吗?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问您 <xliff:g id="STORAGE"><i>^2</i></xliff:g>上的数据(包括照片和视频)吗?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"不再询问"</string>
<string name="allow" msgid="7225948811296386551">"允许"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index 08aefdd53c96..f13a4bd12b57 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"要為「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」開放 <xliff:g id="STORAGE"><i>^3</i></xliff:g>上的「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄存取權嗎?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要為「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」開放「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄的存取權嗎?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"要向「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」開放 <xliff:g id="STORAGE"><i>^2</i></xliff:g>上的相片和影片等資料的存取權嗎?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"不要再詢問"</string>
<string name="allow" msgid="7225948811296386551">"允許"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index 90c932cda872..f8f82820f0d5 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"要允許<xliff:g id="APPNAME"><b>^1</b></xliff:g>存取 <xliff:g id="STORAGE"><i>^3</i></xliff:g>上的「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄嗎?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要允許<xliff:g id="APPNAME"><b>^1</b></xliff:g>存取「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄嗎?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"要允許「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」存取 <xliff:g id="STORAGE"><i>^2</i></xliff:g>上的資料 (包括相片和影片) 嗎?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"不要再詢問"</string>
<string name="allow" msgid="7225948811296386551">"允許"</string>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index e83bb3dee48e..a0b9f7f7c526 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -111,6 +111,7 @@
<string name="rename_error" msgid="4203041674883412606">"Yehlulekile ukuqamba kabusha idokhumenti"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Amanye amafayela aguqulelwe"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Nika i-<xliff:g id="APPNAME"><b>^1</b></xliff:g> ukufinyelela ekuqondiseni kwe-<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ku-<xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Nika ukufinyelela kwe-<xliff:g id="APPNAME"><b>^1</b></xliff:g> kwinkomba ye-<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Nikeza i-<xliff:g id="APPNAME"><b>^1</b></xliff:g> ukufinyelela kudatha yakho, okufaka izithombe namavidiyo, ku-<xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Ungaphindi ubuze"</string>
<string name="allow" msgid="7225948811296386551">"Vumela"</string>
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 1660e26af4f8..cf0643d8ceaa 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -31,6 +31,7 @@
<color name="accent">@*android:color/accent_material_light</color>
<color name="accent_dark">@*android:color/accent_material_dark</color>
<color name="action_mode">@color/material_grey_400</color>
+ <color name="status_bar_color">@*android:color/material_blue_grey_950</color>
<color name="band_select_background">#88ffffff</color>
<color name="band_select_border">#44000000</color>
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index 6590bbeda892..f0cab08723a8 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -20,13 +20,15 @@
<!-- Intentionally unset. Vendors should set this in an overlay. -->
<string name="trusted_quick_viewer_package" translatable="false"></string>
+
+ <!-- overridden for RTL langs -->
<bool name="list_divider_inset_left">true</bool>
- <!-- Indicates if the home directory should be hidden in the roots list, that is presented
- in the drawer/left side panel ) -->
- <bool name="home_root_hidden">true</bool>
- <!-- Indicates if the advanced roots like internal storage should be shown in the roots list.
- When enabled there is no menu option to toggle internal storage visibility. -->
- <bool name="advanced_roots_shown">false</bool>
+
+ <!-- Flags setup as productivity oriented in which case Downloads app will be presented
+ as Files app. Including showing of the Documents and "advanced" roots. -->
+ <bool name="productivity_device">false</bool>
+
<!-- Indicates if search view is taking the whole toolbar space -->
<bool name="full_bar_search_view">true</bool>
+
</resources>
diff --git a/packages/DocumentsUI/res/values/dimens.xml b/packages/DocumentsUI/res/values/dimens.xml
index 5af7da33d997..e682994749b9 100644
--- a/packages/DocumentsUI/res/values/dimens.xml
+++ b/packages/DocumentsUI/res/values/dimens.xml
@@ -38,4 +38,8 @@
<dimen name="drag_shadow_size">120dp</dimen>
<dimen name="grid_item_elevation">2dp</dimen>
<dimen name="max_drawer_width">280dp</dimen>
+
+ <dimen name="drag_shadow_width">160dp</dimen>
+ <dimen name="drag_shadow_height">48dp</dimen>
+
</resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index fb557caf84f2..eb99a0d6f879 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -18,9 +18,6 @@
<!-- Title of the documents application [CHAR LIMIT=32] -->
<string name="app_label">Documents</string>
- <!-- Title of the standalone files activity. [CHAR LIMIT=32] -->
- <string name="files_label">Files</string>
-
<!-- Title of the standalone downloads activity. [CHAR LIMIT=32] -->
<string name="downloads_label">Downloads</string>
@@ -223,6 +220,12 @@
<item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
</plurals>
+ <!-- Label text showing user how many items are being dragged. Can be one or more elements. -->
+ <plurals name="elements_dragged">
+ <item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> item</item>
+ <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> items</item>
+ </plurals>
+
<!-- Dialog text shown to users when asking if they want to delete a file (a confirmation) -->
<string name="delete_filename_confirmation_message">Delete \"<xliff:g id="name" example="cat.jpg">%1$s</xliff:g>\"?</string>
<!-- Dialog text shown to users when asking if they want to delete a folder (a confirmation) -->
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index b0996aa6941c..9f09ebc480e5 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -30,6 +30,7 @@
<item name="android:colorAccent">@color/accent</item>
<item name="colorActionMode">@color/action_mode</item>
<item name="android:queryBackground">@color/menu_search_background</item>
+ <item name="android:statusBarColor">@color/status_bar_color</item>
<item name="android:listDivider">@*android:drawable/list_divider_material</item>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 87136ef35bc9..4ee37a5988cd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -19,10 +19,9 @@ package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
import static com.android.documentsui.State.ACTION_CREATE;
+import static com.android.documentsui.State.ACTION_GET_CONTENT;
import static com.android.documentsui.State.ACTION_OPEN;
import static com.android.documentsui.State.ACTION_OPEN_TREE;
-import static com.android.documentsui.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
import static com.android.documentsui.State.MODE_GRID;
import android.app.Activity;
@@ -37,14 +36,12 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
-import android.os.MessageQueue;
import android.os.MessageQueue.IdleHandler;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.support.annotation.CallSuper;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -104,16 +101,6 @@ public abstract class BaseActivity extends Activity
@CallSuper
@Override
public void onCreate(Bundle icicle) {
- // This flag is being set here as a result of the bug. When the flag was set in the
- // styles.xml keyboard was messing the layout of dialogs (create dir, rename).
- // Attempts were made to keep the flag in the main theme and to override it in the dialog
- // layout xml or to create separate style for dialog and assign it in styles.xml.
- // None of this brought successful results.
- // Setting the flag works here most probably because of the timing when it is set. Also the
- // setting might not affect the dialogs that are created in new windows or it affects them
- // in the different way that having this in the style.
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
-
// Record the time when onCreate is invoked for metric.
mStartTime = new Date().getTime();
@@ -143,7 +130,6 @@ public abstract class BaseActivity extends Activity
mSearchManager = new SearchViewManager(this, icicle);
DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
- Display.adjustToolbar(toolbar, this);
setActionBar(toolbar);
mNavigator = new NavigationView(
mDrawer,
@@ -228,8 +214,7 @@ public abstract class BaseActivity extends Activity
includeState(state);
// Advanced roots are shown by deafult without menu option if forced by config or intent.
- state.showAdvanced = getResources().getBoolean(R.bool.advanced_roots_shown)
- || intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+ state.showAdvanced = Shared.shouldShowDeviceRoot(this, intent);
// Menu option is shown for whitelisted intents if advanced roots are not shown by default.
state.showAdvancedOption = !state.showAdvanced &&
(state.action == ACTION_OPEN ||
@@ -478,11 +463,11 @@ public abstract class BaseActivity extends Activity
* Method can be overridden if the change of the behavior of the the child activity is needed.
*/
public Uri getDefaultRoot() {
- return Shared.isHomeRootHidden(this)
- ? DocumentsContract.buildRootUri("com.android.providers.downloads.documents",
- "downloads")
- : DocumentsContract.buildHomeUri();
- }
+ return Shared.shouldShowDocumentsRoot(this, getIntent())
+ ? DocumentsContract.buildHomeUri()
+ : DocumentsContract.buildRootUri(
+ "com.android.providers.downloads.documents", "downloads");
+ }
void setDisplayAdvancedDevices(boolean display) {
mState.showAdvanced = display;
@@ -636,12 +621,12 @@ public abstract class BaseActivity extends Activity
return true;
}
} else if (keyCode == KeyEvent.KEYCODE_TAB) {
- Metrics.logKeyboardAction(this, keyCode);
+ Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_SWITCH_FOCUS);
// Tab toggles focus on the navigation drawer.
toggleNavDrawerFocus();
return true;
} else if (keyCode == KeyEvent.KEYCODE_DEL) {
- Metrics.logKeyboardAction(this, keyCode);
+ Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_BACK);
popDir();
return true;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Display.java b/packages/DocumentsUI/src/com/android/documentsui/Display.java
index d46a3eac94e9..8b13222dcce7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Display.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Display.java
@@ -20,8 +20,6 @@ import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.util.TypedValue;
-import android.view.WindowManager;
-import android.widget.Toolbar;
/*
* Convenience class for getting display related attributes
@@ -47,41 +45,12 @@ public final class Display {
* Returns action bar height in raw pixels.
*/
public static float actionBarHeight(Context context) {
- int height = 0;
+ int actionBarHeight = 0;
TypedValue tv = new TypedValue();
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
- height = TypedValue.complexToDimensionPixelSize(tv.data,
+ actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,
context.getResources().getDisplayMetrics());
}
- return height;
- }
-
- /*
- * Returns status bar height in raw pixels.
- */
- private static int statusBarHeight(Context context) {
- int height = 0;
- int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
- "android");
- if (resourceId > 0) {
- height = context.getResources().getDimensionPixelSize(resourceId);
- }
- return height;
- }
-
- /*
- * Adjusts toolbar for the layout with translucent status bar. Increases the
- * height of the toolbar and adds padding at the top to accommodate status bar visible above
- * toolbar.
- */
- public static void adjustToolbar(Toolbar toolbar, Activity activity) {
- if ((activity.getWindow().getAttributes().flags
- & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) {
- int statusBarHeight = Display.statusBarHeight(activity);
- toolbar.getLayoutParams().height = (int) (Display.actionBarHeight(activity)
- + statusBarHeight);
- toolbar.setPadding(toolbar.getPaddingLeft(), statusBarHeight, toolbar.getPaddingRight(),
- toolbar.getPaddingBottom());
- }
+ return actionBarHeight;
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 5788420a053c..40b54d34eb03 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -203,8 +203,8 @@ public class DocumentsActivity extends BaseActivity {
mState.action == ACTION_PICK_COPY_DESTINATION) {
title = getResources().getString(R.string.title_save);
} else {
- // If all else fails, just call it "Downloads".
- title = getResources().getString(R.string.downloads_label);
+ // If all else fails, just call it "Documents".
+ title = getResources().getString(R.string.app_label);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
index 900544220cce..5ea6cfa73fcd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -69,7 +69,7 @@ public class DocumentsApplication extends Application {
final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
mRoots = new RootsCache(this);
- mRoots.updateAsync();
+ mRoots.updateAsync(false);
mThumbnails = new ThumbnailCache(memoryClassBytes / 4);
@@ -105,7 +105,7 @@ public class DocumentsApplication extends Application {
final String packageName = data.getSchemeSpecificPart();
mRoots.updatePackageAsync(packageName);
} else {
- mRoots.updateAsync();
+ mRoots.updateAsync(true);
}
}
};
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index 7a4099ae791e..14e6b69bfc19 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -84,7 +84,7 @@ abstract class DrawerController implements DrawerListener {
View drawer = activity.findViewById(R.id.drawer_roots);
Toolbar toolbar = (Toolbar) activity.findViewById(R.id.roots_toolbar);
- Display.adjustToolbar(toolbar, activity);
+
drawer.getLayoutParams().width = calculateDrawerWidth(activity);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index d4439d8b480f..527eb7804fb7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -180,7 +180,10 @@ public class FilesActivity extends BaseActivity {
@Override
public String getDrawerTitle() {
- return getResources().getString(R.string.downloads_label);
+ Intent intent = getIntent();
+ return (intent != null && intent.hasExtra(Intent.EXTRA_TITLE))
+ ? intent.getStringExtra(Intent.EXTRA_TITLE)
+ : getTitle().toString();
}
@Override
@@ -349,21 +352,21 @@ public class FilesActivity extends BaseActivity {
case KeyEvent.KEYCODE_A:
dir = getDirectoryFragment();
if (dir != null) {
- Metrics.logKeyboardAction(this, keyCode);
+ Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_SELECT_ALL);
dir.selectAllFiles();
}
return true;
case KeyEvent.KEYCODE_C:
dir = getDirectoryFragment();
if (dir != null) {
- Metrics.logKeyboardAction(this, keyCode);
+ Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_COPY);
dir.copySelectedToClipboard();
}
return true;
case KeyEvent.KEYCODE_V:
dir = getDirectoryFragment();
if (dir != null) {
- Metrics.logKeyboardAction(this, keyCode);
+ Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_PASTE);
dir.pasteFromClipboard();
}
return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
index 7930c28fc6c2..5cb6ca347896 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
@@ -87,9 +87,24 @@ public class LauncherActivity extends Activity {
startActivity(intent);
}
- static final Intent createLaunchIntent(Context context) {
- Intent intent = new Intent(context, FilesActivity.class);
+ static final Intent createLaunchIntent(Activity activity) {
+ Intent intent = new Intent(activity, FilesActivity.class);
intent.setData(buildLaunchUri());
+
+ // Relay any config overrides bits present in the original intent.
+ Intent original = activity.getIntent();
+ if (original != null) {
+ if (original.hasExtra(Shared.EXTRA_PRODUCTIVITY_MODE)) {
+ intent.putExtra(
+ Shared.EXTRA_PRODUCTIVITY_MODE,
+ original.getBooleanExtra(Shared.EXTRA_PRODUCTIVITY_MODE, false));
+ }
+ if (original.hasExtra(Intent.EXTRA_TITLE)) {
+ intent.putExtra(
+ Intent.EXTRA_TITLE,
+ original.getStringExtra(Intent.EXTRA_TITLE));
+ }
+ }
return intent;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index a4a67f96a3ee..05cc7e66f98c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -296,13 +296,13 @@ public final class Metrics {
// Do not change or rearrange these values, that will break historical data. Only add to the
// list.
// Do not use negative numbers or zero; clearcut only handles positive integers.
- private static final int ACTION_KEYBOARD_OTHER = 1;
- private static final int ACTION_KEYBOARD_PASTE = 2;
- private static final int ACTION_KEYBOARD_COPY = 3;
- private static final int ACTION_KEYBOARD_DELETE = 4;
- private static final int ACTION_KEYBOARD_SELECT_ALL = 5;
- private static final int ACTION_KEYBOARD_BACK = 6;
- private static final int ACTION_KEYBOARD_SWITCH_FOCUS = 7;
+ public static final int ACTION_KEYBOARD_OTHER = 1;
+ public static final int ACTION_KEYBOARD_PASTE = 2;
+ public static final int ACTION_KEYBOARD_COPY = 3;
+ public static final int ACTION_KEYBOARD_DELETE = 4;
+ public static final int ACTION_KEYBOARD_SELECT_ALL = 5;
+ public static final int ACTION_KEYBOARD_BACK = 6;
+ public static final int ACTION_KEYBOARD_SWITCH_FOCUS = 7;
@IntDef(flag = false, value = {
ACTION_KEYBOARD_OTHER,
@@ -525,31 +525,8 @@ public final class Metrics {
* @param context
* @param keyCode
*/
- public static void logKeyboardAction(Context context, int keyCode) {
- @KeyboardAction int keyboardAction = ACTION_KEYBOARD_OTHER;
- switch (keyCode) {
- case KeyEvent.KEYCODE_V:
- keyboardAction = ACTION_KEYBOARD_PASTE;
- break;
- case KeyEvent.KEYCODE_C:
- keyboardAction = ACTION_KEYBOARD_COPY;
- break;
- case KeyEvent.KEYCODE_FORWARD_DEL:
- keyboardAction = ACTION_KEYBOARD_DELETE;
- break;
- case KeyEvent.KEYCODE_A:
- keyboardAction = ACTION_KEYBOARD_SELECT_ALL;
- break;
- case KeyEvent.KEYCODE_DEL:
- keyboardAction = ACTION_KEYBOARD_BACK;
- break;
- case KeyEvent.KEYCODE_TAB:
- keyboardAction = ACTION_KEYBOARD_SWITCH_FOCUS;
- break;
- default:
- break;
- }
- logHistogram(context, COUNT_KEYBOARD_ACTION, keyboardAction);
+ public static void logKeyboardAction(Context context, @KeyboardAction int action) {
+ logHistogram(context, COUNT_KEYBOARD_ACTION, action);
}
/**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 09fadc98a7e0..594e02f0a01d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -122,7 +122,7 @@ public class RootsCache {
/**
* Gather roots from all known storage providers.
*/
- public void updateAsync() {
+ public void updateAsync(boolean forceRefreshAll) {
// NOTE: This method is called when the UI language changes.
// For that reason we update our RecentsRoot to reflect
@@ -139,14 +139,15 @@ public class RootsCache {
| Root.FLAG_SUPPORTS_CREATE));
assert(mRecentsRoot.availableBytes == -1);
- new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ new UpdateTask(forceRefreshAll, null)
+ .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
* Gather roots from storage providers belonging to given package name.
*/
public void updatePackageAsync(String packageName) {
- new UpdateTask(packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ new UpdateTask(false, packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
@@ -223,23 +224,22 @@ public class RootsCache {
}
private class UpdateTask extends AsyncTask<Void, Void, Void> {
+ private final boolean mForceRefreshAll;
private final String mForceRefreshPackage;
private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create();
private final HashSet<String> mTaskStoppedAuthorities = new HashSet<>();
/**
- * Update all roots.
+ * Create task to update roots cache.
+ *
+ * @param forceRefreshAll when true, all previously cached values for
+ * all packages should be ignored.
+ * @param forceRefreshPackage when non-null, all previously cached
+ * values for this specific package should be ignored.
*/
- public UpdateTask() {
- this(null);
- }
-
- /**
- * Force update roots belonging to given package name. Other roots will
- * be copied from cached {@link #mRoots} values.
- */
- public UpdateTask(String forceRefreshPackage) {
+ public UpdateTask(boolean forceRefreshAll, String forceRefreshPackage) {
+ mForceRefreshAll = forceRefreshAll;
mForceRefreshPackage = forceRefreshPackage;
}
@@ -247,14 +247,6 @@ public class RootsCache {
protected Void doInBackground(Void... params) {
final long start = SystemClock.elapsedRealtime();
- if (mForceRefreshPackage != null) {
- // We must have previously cached values to fill in non-matching
- // packages, so wait around for successful first load.
- if (!waitForFirstLoad()) {
- return null;
- }
- }
-
mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot);
final ContentResolver resolver = mContext.getContentResolver();
@@ -300,7 +292,8 @@ public class RootsCache {
return;
}
- final boolean forceRefresh = Objects.equals(mForceRefreshPackage, info.packageName);
+ final boolean forceRefresh = mForceRefreshAll
+ || Objects.equals(info.packageName, mForceRefreshPackage);
mTaskRoots.putAll(info.authority, loadRootsForAuthority(mContext.getContentResolver(),
info.authority, forceRefresh));
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 5f665c0e4dd5..8bbcc306af9a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -17,8 +17,8 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.State.ACTION_OPEN_TREE;
+import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
@@ -319,7 +319,8 @@ public class RootsFragment extends Fragment {
for (final RootInfo root : roots) {
final RootItem item = new RootItem(root);
- if (root.isHome() && Shared.isHomeRootHidden(context)) {
+ if (root.isHome() &&
+ !Shared.shouldShowDocumentsRoot(context, ((Activity) context).getIntent())) {
continue;
} else if (root.isLibrary()) {
if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 2c60d4a3212f..1ba836a7fa4a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -16,19 +16,16 @@
package com.android.documentsui;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Configuration;
+import android.provider.DocumentsContract;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.view.WindowManager;
-import com.android.documentsui.State.ActionType;
-
-import static com.android.documentsui.State.ACTION_OPEN_TREE;
-
-import android.app.AlertDialog;
-
import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
@@ -45,10 +42,21 @@ public final class Shared {
"com.android.documentsui.PICK_COPY_DESTINATION";
/**
+ * Extra flag allowing app to be opened in productivity mode (less downloadsy).
+ * Useful developers and the likes. When set to true overrides the default
+ * config value of productivity_device.
+ */
+ public static final String EXTRA_PRODUCTIVITY_MODE = "com.android.documentsui.PRODUCTIVITY";
+
+ /**
* Extra boolean flag for {@link ACTION_PICK_COPY_DESTINATION}, which
* specifies if the destination directory needs to create new directory or not.
*/
public static final String EXTRA_DIRECTORY_COPY = "com.android.documentsui.DIRECTORY_COPY";
+
+ /**
+ * Extra flag used to store the current stack so user opens in right spot.
+ */
public static final String EXTRA_STACK = "com.android.documentsui.STACK";
/**
@@ -175,10 +183,33 @@ public final class Shared {
}
/*
- * Indicates if the home directory should be hidden in the roots list.
+ * Returns true if app is running in "productivity mode".
*/
- public static boolean isHomeRootHidden(Context context) {
- return context.getResources().getBoolean(R.bool.home_root_hidden);
+ public static boolean productivityMode(Context context) {
+ return context.getResources().getBoolean(R.bool.productivity_device);
}
+ /*
+ * Returns true if app is running in "productivity mode".
+ */
+ private static boolean isProductivityMode(Context context, Intent intent) {
+ return intent.getBooleanExtra(
+ Shared.EXTRA_PRODUCTIVITY_MODE,
+ context.getResources().getBoolean(R.bool.productivity_device));
+ }
+
+ /*
+ * Returns true if "Documents" root should be shown.
+ */
+ public static boolean shouldShowDocumentsRoot(Context context, Intent intent) {
+ return isProductivityMode(context, intent);
+ }
+
+ /*
+ * Returns true if device root should be shown.
+ */
+ public static boolean shouldShowDeviceRoot(Context context, Intent intent) {
+ return isProductivityMode(context, intent)
+ || intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+ }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index c7d60e3d1133..f239eb45552b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -123,9 +123,6 @@ public class State implements android.os.Parcelable {
/** Instance state for every shown directory */
public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
- /** UI selection */
- public Selection selectedDocuments = new Selection();
-
/** Currently copying file */
public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<>();
@@ -202,7 +199,6 @@ public class State implements android.os.Parcelable {
out.writeInt(external ? 1 : 0);
DurableUtils.writeToParcel(out, stack);
out.writeMap(dirState);
- out.writeParcelable(selectedDocuments, 0);
out.writeList(selectedDocumentsForCopy);
out.writeList(excludedAuthorities);
out.writeInt(openableOnly ? 1 : 0);
@@ -233,7 +229,6 @@ public class State implements android.os.Parcelable {
state.external = in.readInt() != 0;
DurableUtils.readFromParcel(in, state.stack);
in.readMap(state.dirState, loader);
- state.selectedDocuments = in.readParcelable(loader);
in.readList(state.selectedDocumentsForCopy, loader);
in.readList(state.excludedAuthorities, loader);
state.openableOnly = in.readInt() != 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 20316fff31b4..1c85a8aba0b1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -40,10 +40,12 @@ import android.content.Loader;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.Point;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Parcel;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
@@ -72,8 +74,8 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
-import android.widget.Toolbar;
import android.widget.TextView;
+import android.widget.Toolbar;
import com.android.documentsui.BaseActivity;
import com.android.documentsui.DirectoryLoader;
@@ -106,6 +108,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@@ -224,7 +227,8 @@ public class DirectoryFragment extends Fragment
mStateKey = buildStateKey(mRoot, mDocument);
mQuery = args.getString(Shared.EXTRA_QUERY);
mType = args.getInt(Shared.EXTRA_TYPE);
- mSelection = args.getParcelable(Shared.EXTRA_SELECTION);
+ final Selection selection = args.getParcelable(Shared.EXTRA_SELECTION);
+ mSelection = selection != null ? selection : new Selection();
mSearchMode = args.getBoolean(Shared.EXTRA_SEARCH_MODE);
mIconHelper = new IconHelper(context, MODE_GRID);
@@ -288,14 +292,25 @@ public class DirectoryFragment extends Fragment
outState.putParcelable(Shared.EXTRA_ROOT, mRoot);
outState.putParcelable(Shared.EXTRA_DOC, mDocument);
outState.putString(Shared.EXTRA_QUERY, mQuery);
- outState.putParcelable(Shared.EXTRA_SELECTION, mSelection);
- outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
+ // Workaround. To avoid crash, write only up to 512 KB of selection.
+ // If more files are selected, then the selection will be lost.
+ final Parcel parcel = Parcel.obtain();
+ try {
+ mSelection.writeToParcel(parcel, 0);
+ if (parcel.dataSize() <= 512 * 1024) {
+ outState.putParcelable(Shared.EXTRA_SELECTION, mSelection);
+ }
+ } finally {
+ parcel.recycle();
+ }
+
+ outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
}
@Override
public void onActivityResult(@RequestCode int requestCode, int resultCode, Intent data) {
- switch(requestCode) {
+ switch (requestCode) {
case REQUEST_COPY_DESTINATION:
handleCopyResult(resultCode, data);
break;
@@ -488,24 +503,19 @@ public class DirectoryFragment extends Fragment
@Override
public void onSelectionChanged() {
mSelectionManager.getSelection(mSelected);
- TypedValue color = new TypedValue();
if (mSelected.size() > 0) {
if (DEBUG) Log.d(TAG, "Maybe starting action mode.");
if (mActionMode == null) {
if (DEBUG) Log.d(TAG, "Yeah. Starting action mode.");
mActionMode = getActivity().startActionMode(this);
}
- getActivity().getTheme().resolveAttribute(R.attr.colorActionMode, color, true);
updateActionMenu();
} else {
if (DEBUG) Log.d(TAG, "Finishing action mode.");
if (mActionMode != null) {
mActionMode.finish();
}
- getActivity().getTheme().resolveAttribute(
- android.R.attr.colorPrimaryDark, color, true);
}
- getActivity().getWindow().setStatusBarColor(color.data);
if (mActionMode != null) {
final String title = Shared.getQuantityString(getActivity(),
@@ -1063,8 +1073,19 @@ public class DirectoryFragment extends Fragment
}
public void selectAllFiles() {
+ // Exclude disabled files
+ List<String> enabled = new ArrayList<String>();
+ for (String id : mAdapter.getModelIds()) {
+ Cursor cursor = getModel().getItem(id);
+ String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+ int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+ if (isDocumentEnabled(docMimeType, docFlags)) {
+ enabled.add(id);
+ }
+ }
+
// Only select things currently visible in the adapter.
- boolean changed = mSelectionManager.setItemsSelected(mAdapter.getModelIds(), true);
+ boolean changed = mSelectionManager.setItemsSelected(enabled, true);
if (changed) {
updateDisplayState();
}
@@ -1217,41 +1238,68 @@ public class DirectoryFragment extends Fragment
DocumentInfo.fromDirectoryCursor(cursor));
}
- private Drawable getDragShadowIcon(List<DocumentInfo> docs) {
- if (docs.size() == 1) {
- final DocumentInfo doc = docs.get(0);
- return mIconHelper.getDocumentIcon(getActivity(), doc.authority, doc.documentId,
- doc.mimeType, doc.icon);
- }
- return getActivity().getDrawable(R.drawable.ic_doc_generic);
- }
+ private static class DragShadowBuilder extends View.DragShadowBuilder {
+
+ private final Context mContext;
+ private final IconHelper mIconHelper;
+ private final LayoutInflater mInflater;
+ private final View mShadowView;
+ private final TextView mTitle;
+ private final ImageView mIcon;
+ private final int mWidth;
+ private final int mHeight;
+
+ public DragShadowBuilder(Context context, IconHelper iconHelper, List<DocumentInfo> docs) {
+ mContext = context;
+ mIconHelper = iconHelper;
+ mInflater = LayoutInflater.from(context);
+
+ mWidth = mContext.getResources().getDimensionPixelSize(R.dimen.drag_shadow_width);
+ mHeight= mContext.getResources().getDimensionPixelSize(R.dimen.drag_shadow_height);
- private class DrawableShadowBuilder extends View.DragShadowBuilder {
+ mShadowView = mInflater.inflate(R.layout.drag_shadow_layout, null);
+ mTitle = (TextView) mShadowView.findViewById(android.R.id.title);
+ mIcon = (ImageView) mShadowView.findViewById(android.R.id.icon);
- private final Drawable mShadow;
+ mTitle.setText(getTitle(docs));
+ mIcon.setImageDrawable(getIcon(docs));
+ }
- private final int mShadowDimension;
+ private Drawable getIcon(List<DocumentInfo> docs) {
+ if (docs.size() == 1) {
+ final DocumentInfo doc = docs.get(0);
+ return mIconHelper.getDocumentIcon(mContext, doc.authority, doc.documentId,
+ doc.mimeType, doc.icon);
+ }
+ return mContext.getDrawable(R.drawable.ic_doc_generic);
+ }
- public DrawableShadowBuilder(Drawable shadow) {
- mShadow = shadow;
- mShadowDimension = getResources().getDimensionPixelSize(
- R.dimen.drag_shadow_size);
- mShadow.setBounds(0, 0, mShadowDimension, mShadowDimension);
+ private String getTitle(List<DocumentInfo> docs) {
+ if (docs.size() == 1) {
+ final DocumentInfo doc = docs.get(0);
+ return doc.displayName;
+ }
+ return Shared.getQuantityString(mContext, R.plurals.elements_dragged, docs.size());
}
@Override
public void onProvideShadowMetrics(
Point shadowSize, Point shadowTouchPoint) {
- shadowSize.set(mShadowDimension, mShadowDimension);
- shadowTouchPoint.set(mShadowDimension / 2, mShadowDimension / 2);
+ shadowSize.set(mWidth, mHeight);
+ shadowTouchPoint.set(mWidth, mHeight);
}
@Override
public void onDrawShadow(Canvas canvas) {
- mShadow.draw(canvas);
+ Rect r = canvas.getClipBounds();
+ // Calling measure is necessary in order for all child views to get correctly laid out.
+ mShadowView.measure(
+ View.MeasureSpec.makeMeasureSpec(r.right- r.left, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(r.top- r.bottom, View.MeasureSpec.EXACTLY));
+ mShadowView.layout(r.left, r.top, r.right, r.bottom);
+ mShadowView.draw(canvas);
}
}
-
/**
* Abstract task providing support for loading documents *off*
* the main thread. And if it isn't obvious, creating a list
@@ -1339,7 +1387,7 @@ public class DirectoryFragment extends Fragment
// This has to be handled here instead of in a keyboard shortcut, because
// keyboard shortcuts all have to be modified with the 'Ctrl' key.
if (mSelectionManager.hasSelection()) {
- Metrics.logKeyboardAction(getContext(), keyCode);
+ Metrics.logKeyboardAction(getContext(), Metrics.ACTION_KEYBOARD_DELETE);
deleteDocuments(mSelectionManager.getSelection());
}
// Always handle the key, even if there was nothing to delete. This is a
@@ -1402,7 +1450,7 @@ public class DirectoryFragment extends Fragment
}
v.startDragAndDrop(
mClipper.getClipDataForDocuments(docs),
- new DrawableShadowBuilder(getDragShadowIcon(docs)),
+ new DragShadowBuilder(getActivity(), mIconHelper, docs),
getDisplayState().stack.peek(),
View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ |
View.DRAG_FLAG_GLOBAL_URI_WRITE
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index faa8e3892f61..016cc9e889df 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -148,11 +148,15 @@ public abstract class FragmentTuner {
MenuItem share = menu.findItem(R.id.menu_share);
MenuItem delete = menu.findItem(R.id.menu_delete);
MenuItem rename = menu.findItem(R.id.menu_rename);
+ MenuItem selectAll = menu.findItem(R.id.menu_select_all);
open.setVisible(true);
share.setVisible(false);
delete.setVisible(false);
rename.setVisible(false);
+ selectAll.setVisible(mState.allowMultiple);
+
+ Menus.disableHiddenItems(menu);
}
@Override
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index f2949196f2a1..69f0e677eb04 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -22,8 +22,10 @@ import static com.android.documentsui.StubProvider.ROOT_1_ID;
import android.app.DownloadManager;
import android.app.DownloadManager.Request;
import android.content.Context;
+import android.content.Intent;
import android.net.Uri;
import android.os.RemoteException;
+import android.provider.DocumentsContract;
import android.support.test.uiautomator.Configurator;
import android.support.test.uiautomator.UiObject;
import android.test.suitebuilder.annotation.LargeTest;
@@ -69,11 +71,10 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
ROOT_1_ID);
// Separate logic for "Documents" root, which presence depends on the config setting
- boolean homeRootHidden = context.getResources().getBoolean(R.bool.home_root_hidden);
- if (homeRootHidden) {
- bots.roots.assertRootsAbsent("Documents");
- } else {
+ if (Shared.shouldShowDocumentsRoot(context, new Intent(DocumentsContract.ACTION_BROWSE))) {
bots.roots.assertRootsPresent("Documents");
+ } else {
+ bots.roots.assertRootsAbsent("Documents");
}
}
diff --git a/packages/Keyguard/res/drawable/ic_backspace_24dp.xml b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml
index 47c8d14330c0..1e4022ea402b 100644
--- a/packages/Keyguard/res/drawable/ic_backspace_24dp.xml
+++ b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml
@@ -15,6 +15,7 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
+ android:autoMirrored="true"
android:height="24dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
diff --git a/packages/Keyguard/res/values/attrs.xml b/packages/Keyguard/res/values/attrs.xml
index 96a5bcc5fcbc..7cfe6316084f 100644
--- a/packages/Keyguard/res/values/attrs.xml
+++ b/packages/Keyguard/res/values/attrs.xml
@@ -32,6 +32,9 @@
<declare-styleable name="PasswordTextView">
<attr name="scaledTextSize" format="integer" />
+ <attr name="android:gravity" />
+ <attr name="dotSize" format="dimension" />
+ <attr name="charPadding" format="dimension" />
</declare-styleable>
<declare-styleable name="CarrierText">
diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
index ef8bb0be0d14..2ff7e121721a 100644
--- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
+++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
@@ -71,6 +71,10 @@ public class NumPadKey extends ViewGroup {
}
public NumPadKey(Context context, AttributeSet attrs, int defStyle) {
+ this(context, attrs, defStyle, R.layout.keyguard_num_pad_key);
+ }
+
+ protected NumPadKey(Context context, AttributeSet attrs, int defStyle, int contentResource) {
super(context, attrs, defStyle);
setFocusable(true);
@@ -92,7 +96,7 @@ public class NumPadKey extends ViewGroup {
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.keyguard_num_pad_key, this, true);
+ inflater.inflate(contentResource, this, true);
mDigitText = (TextView) findViewById(R.id.digit_text);
mDigitText.setText(Integer.toString(mDigit));
@@ -113,7 +117,11 @@ public class NumPadKey extends ViewGroup {
}
}
- setBackground(mContext.getDrawable(R.drawable.ripple_drawable));
+ a = context.obtainStyledAttributes(attrs, android.R.styleable.View);
+ if (!a.hasValueOrEmpty(android.R.styleable.View_background)) {
+ setBackground(mContext.getDrawable(R.drawable.ripple_drawable));
+ }
+ a.recycle();
setContentDescription(mDigitText.getText().toString());
}
diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
index 50e7ecb92ffc..6eea81bf4014 100644
--- a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
@@ -33,6 +33,7 @@ import android.provider.Settings;
import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.Gravity;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -81,6 +82,7 @@ public class PasswordTextView extends View {
* The raw text size, will be multiplied by the scaled density when drawn
*/
private final int mTextHeightRaw;
+ private final int mGravity;
private ArrayList<CharState> mTextChars = new ArrayList<>();
private String mText = "";
private Stack<CharState> mCharPool = new Stack<>();
@@ -118,6 +120,12 @@ public class PasswordTextView extends View {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PasswordTextView);
try {
mTextHeightRaw = a.getInt(R.styleable.PasswordTextView_scaledTextSize, 0);
+ mGravity = a.getInt(R.styleable.PasswordTextView_android_gravity, Gravity.CENTER);
+ mDotSize = a.getDimensionPixelSize(R.styleable.PasswordTextView_dotSize,
+ getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size));
+ mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding,
+ getContext().getResources().getDimensionPixelSize(
+ R.dimen.password_char_padding));
} finally {
a.recycle();
}
@@ -125,9 +133,6 @@ public class PasswordTextView extends View {
mDrawPaint.setTextAlign(Paint.Align.CENTER);
mDrawPaint.setColor(0xffffffff);
mDrawPaint.setTypeface(Typeface.create("sans-serif-light", 0));
- mDotSize = getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size);
- mCharPadding = getContext().getResources().getDimensionPixelSize(R.dimen
- .password_char_padding);
mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -142,11 +147,23 @@ public class PasswordTextView extends View {
@Override
protected void onDraw(Canvas canvas) {
float totalDrawingWidth = getDrawingWidth();
- float currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2;
+ float currentDrawPosition;
+ if ((mGravity & Gravity.START) != 0) {
+ if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+ currentDrawPosition = getWidth() - getPaddingRight() - totalDrawingWidth;
+ } else {
+ currentDrawPosition = getPaddingLeft();
+ }
+ } else {
+ currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2;
+ }
int length = mTextChars.size();
Rect bounds = getCharBounds();
int charHeight = (bounds.bottom - bounds.top);
- float yPosition = getHeight() / 2;
+ float yPosition =
+ (getHeight() - getPaddingBottom() - getPaddingTop()) / 2 + getPaddingTop();
+ canvas.clipRect(getPaddingLeft(), getPaddingTop(),
+ getWidth()-getPaddingRight(), getHeight()-getPaddingBottom());
float charLength = bounds.right - bounds.left;
for (int i = 0; i < length; i++) {
CharState charState = mTextChars.get(i);
diff --git a/packages/PrintServiceRecommendationService/res/values/strings.xml b/packages/PrintServiceRecommendationService/res/values/strings.xml
index 83d38000395a..07d0004fa09b 100644
--- a/packages/PrintServiceRecommendationService/res/values/strings.xml
+++ b/packages/PrintServiceRecommendationService/res/values/strings.xml
@@ -23,7 +23,7 @@
<string name="plugin_vendor_brother">Brother</string>
<string name="plugin_vendor_canon">Canon</string>
<string name="plugin_vendor_xerox">Xerox</string>
- <string name="plugin_vendor_samsung">Samsung Electorics</string>
+ <string name="plugin_vendor_samsung">Samsung Electronics</string>
<string name="plugin_vendor_epson">Epson</string>
<string name="plugin_vendor_konika_minolta">Konika Minolta</string>
<string name="plugin_vendor_fuji">Fuji</string>
diff --git a/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
index fda2768c8678..119943cd5f9f 100644
--- a/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
+++ b/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
@@ -46,7 +46,7 @@
<vendor>
<name>@string/plugin_vendor_canon</name>
- <package>com.xerox.printservice</package>
+ <package>jp.co.canon.android.printservice.plugin</package>
<mdns-names>
<mdns-name>Canon</mdns-name>
</mdns-names>
@@ -54,7 +54,7 @@
<vendor>
<name>@string/plugin_vendor_xerox</name>
- <package>jp.co.canon.android.printservice.plugin</package>
+ <package>com.xerox.printservice</package>
<mdns-names>
<mdns-name>Xerox</mdns-name>
</mdns-names>
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index a87afe0a77a9..248d0c05934a 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -239,7 +239,8 @@
android:singleLine="true"
android:ellipsize="end"
android:visibility="visible"
- android:inputType="textNoSuggestions">
+ android:inputType="number"
+ android:digits="0123456789 ,-">
</com.android.printspooler.widget.CustomErrorEditText>
</LinearLayout>
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 0224c6c596c0..fa5ec3f5269c 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Aanbevole dienste"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Gedeaktiveerde dienste"</string>
<string name="all_services_title" msgid="5578662754874906455">"Alle dienste"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Installeer om <xliff:g id="COUNT_1">%1$s</xliff:g> drukkers te ontdek</item>
+ <item quantity="one">Installeer om <xliff:g id="COUNT_0">%1$s</xliff:g> drukker ontdek</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Druk tans <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kanselleer tans <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Drukkerfout by <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index 98255d46f2c9..5ada8d31ed42 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"የሚመከሩ አገልግሎቶች"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"የተሰናከሉ አገልግሎቶች"</string>
<string name="all_services_title" msgid="5578662754874906455">"ሁሉም አገልግሎቶች"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> አታሚዎች ለማግኘት ይጫኑ</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> አታሚዎች ለማግኘት ይጫኑ</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ን በማተም ላይ"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ን በመተው ላይ"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"የአታሚ ስህተት <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 5f0255c5dd8b..1208298bd701 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -76,6 +76,14 @@
<string name="recommended_services_title" msgid="3799434882937956924">"الخدمات الموصى بها"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"الخدمات المعطَّلة"</string>
<string name="all_services_title" msgid="5578662754874906455">"جميع الخدمات"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="zero">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
+ <item quantity="two">التثبيت لاستكشاف طابعتين (<xliff:g id="COUNT_1">%1$s</xliff:g>)</item>
+ <item quantity="few">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
+ <item quantity="many">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعة</item>
+ <item quantity="other">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
+ <item quantity="one">التثبيت لاستكشاف <xliff:g id="COUNT_0">%1$s</xliff:g> طابعة</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"جارٍ طباعة <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"جارٍ إلغاء <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"خطا في الطابعة <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-az-rAZ/strings.xml b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
index b5dfaf89b6ff..4404aadb4e44 100644
--- a/packages/PrintSpooler/res/values-az-rAZ/strings.xml
+++ b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Tövsiyə olunan xidmətlər"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Deaktiv edilmiş xidmətlər"</string>
<string name="all_services_title" msgid="5578662754874906455">"Bütün xidmətlər"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> printeri kəşf etmək üçün quraşdırın</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> printeri kəşf etmək üçün quraşdırın</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> çap edilir"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ləğv edilir"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer xətası <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
index 2ac80028cc32..50ce1f96b912 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -73,6 +73,11 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Preporučene usluge"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Onemogućene usluge"</string>
<string name="all_services_title" msgid="5578662754874906455">"Sve usluge"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Instalirajte da biste otkrili <xliff:g id="COUNT_1">%1$s</xliff:g> štampač</item>
+ <item quantity="few">Instalirajte da biste otkrili <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+ <item quantity="other">Instalirajte da biste otkrili <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Štampa se <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazuje se <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Greška štampača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-be-rBY/strings.xml b/packages/PrintSpooler/res/values-be-rBY/strings.xml
index 13d573ec5921..c264f9266b81 100644
--- a/packages/PrintSpooler/res/values-be-rBY/strings.xml
+++ b/packages/PrintSpooler/res/values-be-rBY/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Рэкамендаваныя службы"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Адключаныя службы"</string>
<string name="all_services_title" msgid="5578662754874906455">"Усе службы"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтар</item>
+ <item quantity="few">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтары</item>
+ <item quantity="many">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтараў</item>
+ <item quantity="other">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтара</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Друк <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Скасоўваецца <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Памылка друку <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index 73c51e9ad1d3..3dd6ec566ce7 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Препоръчителни услуги"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Деактивирани услуги"</string>
<string name="all_services_title" msgid="5578662754874906455">"Всички услуги"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Инсталирайте, за да бъдат открити <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+ <item quantity="one">Инсталирайте, за да бъде открит <xliff:g id="COUNT_0">%1$s</xliff:g> принтер</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"„<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“ се отпечатва"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"„<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“ се анулира"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка в принтера при „<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“"</string>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index 25b4660265f6..3789f21db147 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"প্রস্তাবিত পরিষেবাগুলি"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"অক্ষম করা পরিষেবাগুলি"</string>
<string name="all_services_title" msgid="5578662754874906455">"সমস্ত পরিষেবা"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g>টি মুদ্রক খুঁজে পেতে ইনস্টল করুন</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g>টি মুদ্রক খুঁজে পেতে ইনস্টল করুন</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> প্রিন্ট করা হচ্ছে"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> বাতিল করা হচ্ছে"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> মুদ্রক ত্রুটি"</string>
diff --git a/packages/PrintSpooler/res/values-bs-rBA/strings.xml b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
index 9a17707210da..c3c9bb33e9c3 100644
--- a/packages/PrintSpooler/res/values-bs-rBA/strings.xml
+++ b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
@@ -73,6 +73,11 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Preporučene usluge"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Isključene usluge"</string>
<string name="all_services_title" msgid="5578662754874906455">"Sve usluge"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"> Instaliraj da pronađeš <xliff:g id="COUNT_1">%1$s</xliff:g> štampač</item>
+ <item quantity="few"> Instaliraj da pronađeš <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+ <item quantity="other"> Instaliraj da pronađeš <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Štampa se <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazivanje <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Greška pri štampanju <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index a1df40603404..f65a63c95874 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Serveis recomanats"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Serveis desactivats"</string>
<string name="all_services_title" msgid="5578662754874906455">"Tots els serveis"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Instal·la\'l per detectar <xliff:g id="COUNT_1">%1$s</xliff:g> impressores</item>
+ <item quantity="one">Instal·la\'l per detectar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"S\'està imprimint <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"S\'està cancel·lant <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error d\'impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 55fb21bbc24b..9bfa2719ef49 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Doporučené služby"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Deaktivované služby"</string>
<string name="all_services_title" msgid="5578662754874906455">"Všechny služby"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="few">Instalací objevíte <xliff:g id="COUNT_1">%1$s</xliff:g> tiskárny</item>
+ <item quantity="many">Instalací objevíte <xliff:g id="COUNT_1">%1$s</xliff:g> tiskárny</item>
+ <item quantity="other">Instalací objevíte <xliff:g id="COUNT_1">%1$s</xliff:g> tiskáren</item>
+ <item quantity="one">Instalací objevíte <xliff:g id="COUNT_0">%1$s</xliff:g> tiskárnu</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Tisk úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Rušení úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tiskárny u úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 49417bd75f04..75a0b56f01de 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Anbefalede tjenester"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Deaktiverede tjenester"</string>
<string name="all_services_title" msgid="5578662754874906455">"Alle tjenester"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Installer for at finde <xliff:g id="COUNT_1">%1$s</xliff:g> printer</item>
+ <item quantity="other">Installer for at finde <xliff:g id="COUNT_1">%1$s</xliff:g> printere</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> udskrives"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annulleres"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Udskriften <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> mislykkedes"</string>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index cb7aeee3cd2b..8c6181d31b04 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Empfohlene Dienste"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Deaktivierte Dienste"</string>
<string name="all_services_title" msgid="5578662754874906455">"Alle Dienste"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Installieren, um <xliff:g id="COUNT_1">%1$s</xliff:g> Drucker zu erkennen</item>
+ <item quantity="one">Installieren, um <xliff:g id="COUNT_0">%1$s</xliff:g> Drucker zu erkennen</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> wird gedruckt..."</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> wird abgebrochen..."</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Druckerfehler <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index 4441ea2e9e76..31d3f8333535 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Προτεινόμενες υπηρεσίες"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Υπηρεσίες για άτομα με αναπηρία"</string>
<string name="all_services_title" msgid="5578662754874906455">"Όλες οι υπηρεσίες"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Κάντε εγκατάσταση για να ανακαλύψετε <xliff:g id="COUNT_1">%1$s</xliff:g> εκτυπωτές</item>
+ <item quantity="one">Κάντε εγκατάσταση για να ανακαλύψετε <xliff:g id="COUNT_0">%1$s</xliff:g> εκτυπωτή</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Εκτύπωση <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ακύρωση <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Σφάλμα εκτυπωτή <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-en-rAU/strings.xml b/packages/PrintSpooler/res/values-en-rAU/strings.xml
index f8b6265d8506..5e32ae48be42 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Recommended services"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Disabled services"</string>
<string name="all_services_title" msgid="5578662754874906455">"All services"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
+ <item quantity="one">Install to discover <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Printing <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index f8b6265d8506..5e32ae48be42 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Recommended services"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Disabled services"</string>
<string name="all_services_title" msgid="5578662754874906455">"All services"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
+ <item quantity="one">Install to discover <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Printing <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index f8b6265d8506..5e32ae48be42 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Recommended services"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Disabled services"</string>
<string name="all_services_title" msgid="5578662754874906455">"All services"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
+ <item quantity="one">Install to discover <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Printing <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index 8d555971cedd..a6a9f0780176 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Servicios recomendados"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string>
<string name="all_services_title" msgid="5578662754874906455">"Todos los servicios"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Instala para ver <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+ <item quantity="one">Instala para ver <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Imprimiendo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index 7d08a0efe31a..4f6731d4b3ea 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Servicios recomendados"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string>
<string name="all_services_title" msgid="5578662754874906455">"Todos los servicios"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Instalar para descubrir <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+ <item quantity="one">Instalar para descubrir <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Imprimiendo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 09da3e09e782..3d0516c21858 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Soovitatud teenused"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Keelatud teenused"</string>
<string name="all_services_title" msgid="5578662754874906455">"Kõik teenused"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Installige <xliff:g id="COUNT_1">%1$s</xliff:g> printeri avastamiseks</item>
+ <item quantity="one">Installige <xliff:g id="COUNT_0">%1$s</xliff:g> printeri avastamiseks</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Prinditöö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> printimine"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prinditöö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> tühistamine"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri viga: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-eu-rES/strings.xml b/packages/PrintSpooler/res/values-eu-rES/strings.xml
index 6b760b441cd3..c56692fd333e 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Gomendatutako zerbitzuak"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Desgaitutako zerbitzuak"</string>
<string name="all_services_title" msgid="5578662754874906455">"Zerbitzu guztiak"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Instalatu <xliff:g id="COUNT_1">%1$s</xliff:g> inprimagailu aurkitzeko</item>
+ <item quantity="one">Instalatu <xliff:g id="COUNT_0">%1$s</xliff:g> inprimagailu aurkitzeko</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> inprimatzen"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bertan behera uzten"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Errorea <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> inprimatzean"</string>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index fa105d5bcbcb..8a6c0ddba370 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"خدمات توصیه‌شده"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"خدمات غیرفعال"</string>
<string name="all_services_title" msgid="5578662754874906455">"همه خدمات"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">نصب کنید تا <xliff:g id="COUNT_1">%1$s</xliff:g> چاپگر را پیدا کنید</item>
+ <item quantity="other">نصب کنید تا <xliff:g id="COUNT_1">%1$s</xliff:g> چاپگر را پیدا کنید</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"در حال چاپ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"در حال لغو <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"خطای چاپگر <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index cf051f85891f..3d6897d6bcce 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Suositellut palvelut"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Käytöstä poistetut palvelut"</string>
<string name="all_services_title" msgid="5578662754874906455">"Kaikki palvelut"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Asentamalla voit löytää <xliff:g id="COUNT_1">%1$s</xliff:g> tulostinta.</item>
+ <item quantity="one">Asentamalla voit löytää <xliff:g id="COUNT_0">%1$s</xliff:g> tulostimen.</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Tulostetaan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Peruutetaan työ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Tulostinvirhe työlle <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 11d2875d583c..6c9539a3db80 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Services recommandés"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Services désactivés"</string>
<string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
+ <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Impression de <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> en cours…"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression : « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 6b892816d385..64add68614ee 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Services recommandés"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Services désactivés"</string>
<string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
+ <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Impression de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression pour \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
diff --git a/packages/PrintSpooler/res/values-gl-rES/strings.xml b/packages/PrintSpooler/res/values-gl-rES/strings.xml
index 7ddc9f82c4dd..099159d66682 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Servizos recomendados"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Servizos desactivados"</string>
<string name="all_services_title" msgid="5578662754874906455">"Todos os servizos"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Instala o servizo para atopar <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+ <item quantity="one">Instala o servizo para atopar <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-gu-rIN/strings.xml b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
index 6a7e0df1ac81..b42fdabe4035 100644
--- a/packages/PrintSpooler/res/values-gu-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"ભલામણ કરેલી સેવાઓ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"અક્ષમ કરેલી સેવાઓ"</string>
<string name="all_services_title" msgid="5578662754874906455">"બધી સેવાઓ"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> પ્રિન્ટરની શોધ કરવા માટે ઇન્સ્ટૉલ કરો</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> પ્રિન્ટરની શોધ કરવા માટે ઇન્સ્ટૉલ કરો</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> છાપી રહ્યાં છે"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ને રદ કરી રહ્યું છે"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"પ્રિન્ટર ભૂલ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 377dc62f5e6d..507754a0a4db 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"सुझाई गई सेवाएं"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"अक्षम सेवाएं"</string>
<string name="all_services_title" msgid="5578662754874906455">"सभी सेवाएं"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर खोजने के लिए इंस्टॉल करें</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर खोजने के लिए इंस्टॉल करें</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> प्रिंट हो रहा है"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द हो रहा है"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 8550be40b90f..92c97ea3223f 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -73,6 +73,11 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Preporučene usluge"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Onemogućene usluge"</string>
<string name="all_services_title" msgid="5578662754874906455">"Sve usluge"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Instalirajte da biste pronašli <xliff:g id="COUNT_1">%1$s</xliff:g> pisač</item>
+ <item quantity="few">Instalirajte da biste pronašli <xliff:g id="COUNT_1">%1$s</xliff:g> pisača</item>
+ <item quantity="other">Instalirajte da biste pronašli <xliff:g id="COUNT_1">%1$s</xliff:g> pisača</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Ispisivanje <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazivanje zadatka <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Pogreška pisača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 20789a36ab05..a2e53db859e2 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Javasolt szolgáltatások"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Letiltott szolgáltatások"</string>
<string name="all_services_title" msgid="5578662754874906455">"Minden szolgáltatás"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Telepítés <xliff:g id="COUNT_1">%1$s</xliff:g> nyomtató felfedezéséhez</item>
+ <item quantity="one">Telepítés <xliff:g id="COUNT_0">%1$s</xliff:g> nyomtató felfedezéséhez</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> nyomtatása"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> törlése"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Nyomtatási hiba: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index 895033860b2f..e26c2444280d 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Խորհուրդ տրվող ծառայությունները"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Կասեցված ծառայությունները"</string>
<string name="all_services_title" msgid="5578662754874906455">"Բոլոր ծառայությունները"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Տեղադրեք՝ <xliff:g id="COUNT_1">%1$s</xliff:g> տպիչ հայտնաբերելու համար</item>
+ <item quantity="other">Տեղադրեք՝ <xliff:g id="COUNT_1">%1$s</xliff:g> տպիչ հայտնաբերելու համար</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Տպվում է՝ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>-ը չեղարկվում է"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Տպիչի սխալ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 9b722500e8b5..4ec06441db7a 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Layanan yang disarankan"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Layanan dinonaktifkan"</string>
<string name="all_services_title" msgid="5578662754874906455">"Semua layanan"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Pasang untuk menemukan <xliff:g id="COUNT_1">%1$s</xliff:g> printer</item>
+ <item quantity="one">Pasang untuk menemukan <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Mencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ada kesalahan printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-is-rIS/strings.xml b/packages/PrintSpooler/res/values-is-rIS/strings.xml
index 37abb5a0c8a3..e05f07f4bec1 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Þjónusta sem mælt er með"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Þjónusta við fatlaða"</string>
<string name="all_services_title" msgid="5578662754874906455">"Öll þjónusta"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Settu upp til að finna <xliff:g id="COUNT_1">%1$s</xliff:g> prentara</item>
+ <item quantity="other">Settu upp til að finna <xliff:g id="COUNT_1">%1$s</xliff:g> prentara</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Prentar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hættir við <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Prentaravilla <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index dd4a8cb47a70..39a0a6182206 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Servizi consigliati"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Servizi disattivati"</string>
<string name="all_services_title" msgid="5578662754874906455">"Tutti i servizi"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Installa per rilevare <xliff:g id="COUNT_1">%1$s</xliff:g> stampanti</item>
+ <item quantity="one">Installa per rilevare <xliff:g id="COUNT_0">%1$s</xliff:g> stampante</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Stampa di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annullamento di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Errore della stampante: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 1d813bbc2bac..9aa4104c90f7 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"שירותים מומלצים"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"שירותים מושבתים"</string>
<string name="all_services_title" msgid="5578662754874906455">"כל השירותים"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="two">התקן כדי לגלות <xliff:g id="COUNT_1">%1$s</xliff:g> מדפסות</item>
+ <item quantity="many">התקן כדי לגלות <xliff:g id="COUNT_1">%1$s</xliff:g> מדפסות</item>
+ <item quantity="other">התקן כדי לגלות <xliff:g id="COUNT_1">%1$s</xliff:g> מדפסות</item>
+ <item quantity="one">התקן כדי לגלות מדפסת <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"מדפיס את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"מבטל את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"שגיאת מדפסת ב-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index 946052a43e40..f97efc1a1502 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"推奨されているサービス"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"無効になっているサービス"</string>
<string name="all_services_title" msgid="5578662754874906455">"すべてのサービス"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> 台のプリンタを検索するにはインストールします</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> 台のプリンタを検索するにはインストールします</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>を印刷しています"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>をキャンセルしています"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"プリンタエラー: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index 94152b1ae345..9cb8b39d4035 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"რეკომენდებული სერვისები"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"გათიშული სერვისები"</string>
<string name="all_services_title" msgid="5578662754874906455">"ყველა სერვისი"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">დააინსტალირეთ <xliff:g id="COUNT_1">%1$s</xliff:g> პრინტერის აღმოსაჩენად</item>
+ <item quantity="one">დააინსტალირეთ <xliff:g id="COUNT_0">%1$s</xliff:g> პრინტერის აღმოსაჩენად</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"იბეჭდება <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"მიმდინარეობს <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>-ის გაუქმება"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ბეჭდვის შეცდომა <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index c647dab05d1f..37b2cd3a8862 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Ұсынылған қызметтер"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Өшірілген қызметтер"</string>
<string name="all_services_title" msgid="5578662754874906455">"Барлық қызметтер"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> принтерді табу үшін орнатыңыз</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> принтерді табу үшін орнатыңыз</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> басып шығарылуда"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> жұмысын тоқтатуда"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> принтер қателігі"</string>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index 330edf579094..12d296d3f006 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"សេវាកម្មដែលបានណែនាំ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"សេវាកម្មដែលបិទដំណើរការ"</string>
<string name="all_services_title" msgid="5578662754874906455">"សេវាកម្មទាំងអស់"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">ដំឡើងដើម្បីរកមើលម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ <item quantity="one">ដំឡើងដើម្បីរកមើលម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"កំពុង​​បោះពុម្ព <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"ការ​បោះបង់ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"កំហុស​ម៉ាស៊ីន​បោះពុម្ព <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index f1cef8684cc2..8b1acddcb563 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"ಶಿಫಾರಸು ಮಾಡಲಾದ ಸೇವೆಗಳು"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾದ ಸೇವೆಗಳು"</string>
<string name="all_services_title" msgid="5578662754874906455">"ಎಲ್ಲ ಸೇವೆಗಳು"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> ಪ್ರಿಂಟರ್‌ಗಳನ್ನು ಶೋಧಿಸಲು ಸ್ಥಾಪಿಸಿ</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ಪ್ರಿಂಟರ್‌ಗಳನ್ನು ಶೋಧಿಸಲು ಸ್ಥಾಪಿಸಿ</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ಮುದ್ರಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ರದ್ದು ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ಮುದ್ರಕ ದೋಷ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index d3cc9671b157..e6ca240e7042 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"권장 서비스"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"사용 중지된 서비스"</string>
<string name="all_services_title" msgid="5578662754874906455">"모든 서비스"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g>개 프린터를 표시하려면 설치하세요.</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g>개 프린터를 표시하려면 설치하세요.</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> 인쇄 중"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> 취소 중"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"프린터 오류: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index d84e5d857ad0..ae0b05e2a2f0 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Сунушталган кызматтар"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Өчүрүлгөн кызматтар"</string>
<string name="all_services_title" msgid="5578662754874906455">"Бардык кызматтар"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Орнотсоңуз <xliff:g id="COUNT_1">%1$s</xliff:g> принтер таап аласыз</item>
+ <item quantity="one">Орнотсоңуз <xliff:g id="COUNT_0">%1$s</xliff:g> принтер таап аласыз</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> басылууда"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> токтотулууда"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Принтерде ката кетти: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 6a690538aa8a..2392e4a188ea 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"ບໍລິການທີ່ແນະນຳ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"ບໍລິການທີ່ຖືກປິດການນຳໃຊ້"</string>
<string name="all_services_title" msgid="5578662754874906455">"ບໍລິການທັງໝົດ"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">ຕິດຕັ້ງເພື່ອຄົ້ນພົບເຄື່ອງພິມ <xliff:g id="COUNT_1">%1$s</xliff:g> ເຄື່ອງ</item>
+ <item quantity="one">ຕິດຕັ້ງເພື່ອຄົ້ນພົບເຄື່ອງພິມ <xliff:g id="COUNT_0">%1$s</xliff:g> ເຄື່ອງ</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"ກຳລັງພິມ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"ກຳລັງຍົກເລີກ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ເຄື່ອງພິມເກີດຂໍ້ຜິດພາດ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index ddcaba7275d7..65ccc2be040b 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Rekomenduojamos paslaugos"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Išjungtos paslaugos"</string>
<string name="all_services_title" msgid="5578662754874906455">"Visos paslaugos"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Įdiekite, kad būtų rastas <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvas</item>
+ <item quantity="few">Įdiekite, kad būtų rasti <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvai</item>
+ <item quantity="many">Įdiekite, kad būtų rasta <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvo</item>
+ <item quantity="other">Įdiekite, kad būtų rasta <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvų</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Spausdinama: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Atšaukiama: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Spausdintuvo klaida: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 50ba32d81b44..1bcfe783d239 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -73,6 +73,11 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Ieteiktie pakalpojumi"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Atspējotie pakalpojumi"</string>
<string name="all_services_title" msgid="5578662754874906455">"Visi pakalpojumi"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="zero">Instalējiet, lai atklātu <xliff:g id="COUNT_1">%1$s</xliff:g> printerus</item>
+ <item quantity="one">Instalējiet, lai atklātu <xliff:g id="COUNT_1">%1$s</xliff:g> printeri</item>
+ <item quantity="other">Instalējiet, lai atklātu <xliff:g id="COUNT_1">%1$s</xliff:g> printerus</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Notiek darba <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> drukāšana…"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Pārtrauc drukas darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printera kļūda ar darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-mk-rMK/strings.xml b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
index a18904224852..d29566bc1edf 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Препорачани услуги"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Оневозможени услуги"</string>
<string name="all_services_title" msgid="5578662754874906455">"Сите услуги"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Инсталирајте за да пронајдете <xliff:g id="COUNT_1">%1$s</xliff:g> печатач</item>
+ <item quantity="other">Инсталирајте за да пронајдете <xliff:g id="COUNT_1">%1$s</xliff:g> печатачи</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> се печати"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> се откажува"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка при печатење <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index 56256325f721..16d654c63fc0 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"ശുപാർശ ചെയ്യപ്പെടുന്ന സേവനങ്ങൾ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"പ്രവർത്തനരഹിതമാക്കിയ സേവനങ്ങൾ"</string>
<string name="all_services_title" msgid="5578662754874906455">"എല്ലാ സേവനങ്ങളും"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> പ്രിന്ററുകൾ കണ്ടെത്തുന്നതിന് ഇൻസ്റ്റാൾ ചെയ്യുക</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> പ്രിന്റർ കണ്ടെത്തുന്നതിന് ഇൻസ്റ്റാൾ ചെയ്യുക</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> പ്രിന്റുചെയ്യുന്നു"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> റദ്ദാക്കുന്നു"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"പ്രിന്റർ പിശക് <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index 7797944cc170..ded066566499 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Санал болгосон үйлчилгээ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Идэвхгүй болгосон үйлчилгээ"</string>
<string name="all_services_title" msgid="5578662754874906455">"Бүх үйлчилгээ"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"> <xliff:g id="COUNT_1">%1$s</xliff:g> хэвлэгч олохын тулд суулгах</item>
+ <item quantity="one"> <xliff:g id="COUNT_0">%1$s</xliff:g> хэвлэгч олохын тулд суулгах</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Хэвлэж байна <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Цуцлаж байна <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Принтерийн алдаа <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index ee09db231883..5436635ada1c 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"शिफारस केलेल्या सेवा"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"अक्षम केलल्या सेवा"</string>
<string name="all_services_title" msgid="5578662754874906455">"सर्व सेवा"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी स्थापित करा</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी स्थापित करा</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> मुद्रण करीत आहे"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द करीत आहे"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटी <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 4042c7171853..8af5232f8a16 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Perkhidmatan yang disyorkan"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Perkhidmatan yang dilumpuhkan"</string>
<string name="all_services_title" msgid="5578662754874906455">"Semua perkhidmatan"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Pasang untuk menemui <xliff:g id="COUNT_1">%1$s</xliff:g> pencetak</item>
+ <item quantity="one">Pasang untuk menemui <xliff:g id="COUNT_0">%1$s</xliff:g> pencetak</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Mencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ralat pencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml
index f34ca6782a08..9b5f46aca49f 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"အကြံပြုထားသည့် ဝန်ဆောင်မှုများ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"ပိတ်ထားသည့် ဝန်ဆောင်မှုများ"</string>
<string name="all_services_title" msgid="5578662754874906455">"ဝန်ဆောင်မှုများ အားလုံး"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">ပုံနှိပ်စက် <xliff:g id="COUNT_1">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
+ <item quantity="one">ပုံနှိပ်စက် <xliff:g id="COUNT_0">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကို စာထုတ်နေပါသည်"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကို ပယ်ဖျက်နေပါသည်"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"စာထုတ်စက်မှ အမှား <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 6b74765451dd..82282bad9268 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Anbefalte tjenester"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Tjenester som er slått av"</string>
<string name="all_services_title" msgid="5578662754874906455">"Alle tjenester"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Installer for å finne <xliff:g id="COUNT_1">%1$s</xliff:g> printere</item>
+ <item quantity="one">Installer for å finne <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Skriver ut <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Skriverfeil <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index 8e8bf15f7be9..4cf2f51b288a 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"सिफारिस गरिएका सेवाहरू"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"असक्षम गरिएका सेवाहरू"</string>
<string name="all_services_title" msgid="5578662754874906455">"सबै सेवाहरू"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिन्टरहरू पत्ता लगाउनका लागि स्थापना गर्नुहोस्</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> प्रिन्टर पत्ता लगाउनका लागि स्थापना गर्नुहोस्</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"प्रिन्ट गरिँदै <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"रद्द गरिँदै <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिन्टर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 3c65d8af5d00..83b9a2233166 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Aanbevolen services"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Uitgeschakelde services"</string>
<string name="all_services_title" msgid="5578662754874906455">"Alle services"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Installeren om <xliff:g id="COUNT_1">%1$s</xliff:g> printers te vinden</item>
+ <item quantity="one">Installeren om <xliff:g id="COUNT_0">%1$s</xliff:g> printer te vinden</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> afdrukken"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annuleren"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printerfout <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pa-rIN/strings.xml b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
index 934123bcbef4..5f3366fb4eda 100644
--- a/packages/PrintSpooler/res/values-pa-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀਆਂ ਸੇਵਾਵਾਂ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਸੇਵਾਵਾਂ"</string>
<string name="all_services_title" msgid="5578662754874906455">"ਸਾਰੀਆਂ ਸੇਵਾਵਾਂ"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> ਪ੍ਰਿੰਟਰ ਖੋਜਣ ਲਈ ਸਥਾਪਤ ਕਰੋ</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ਪ੍ਰਿੰਟਰ ਖੋਜਣ ਲਈ ਸਥਾਪਤ ਕਰੋ</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ਨੂੰ ਪ੍ਰਿੰਟ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ਨੂੰ ਰੱਦ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ਪ੍ਰਿੰਟਰ ਅਸ਼ੁੱਧੀ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 80b607076a02..e7fb7b61470e 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Polecane usługi"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Wyłączone usługi"</string>
<string name="all_services_title" msgid="5578662754874906455">"Wszystkie usługi"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="few">Zainstaluj, by wykryć <xliff:g id="COUNT_1">%1$s</xliff:g> drukarki</item>
+ <item quantity="many">Zainstaluj, by wykryć <xliff:g id="COUNT_1">%1$s</xliff:g> drukarek</item>
+ <item quantity="other">Zainstaluj, by wykryć <xliff:g id="COUNT_1">%1$s</xliff:g> drukarki</item>
+ <item quantity="one">Zainstaluj, by wykryć <xliff:g id="COUNT_0">%1$s</xliff:g> drukarkę</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Drukowanie: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Anulowanie: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Błąd drukarki: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rBR/strings.xml b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
index 4bd1161dc153..dd8cdb25ab73 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Serviços recomendados"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string>
<string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+ <item quantity="other">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro ao imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 7660c5c42caa..c1fe7bfb38a8 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Serviços recomendados"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string>
<string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Instale para detetar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+ <item quantity="one">Instale para detetar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"A imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"A cancelar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 4bd1161dc153..dd8cdb25ab73 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Serviços recomendados"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string>
<string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+ <item quantity="other">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro ao imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index dd38c31dc397..b326e09fbd95 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -73,6 +73,11 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Servicii recomandate"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Servicii dezactivate"</string>
<string name="all_services_title" msgid="5578662754874906455">"Toate serviciile"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="few">Instalați pentru a descoperi <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
+ <item quantity="other">Instalați pentru a descoperi <xliff:g id="COUNT_1">%1$s</xliff:g> de imprimante</item>
+ <item quantity="one">Instalați pentru a descoperi <xliff:g id="COUNT_0">%1$s</xliff:g> imprimantă</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Se printează <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Se anulează <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Eroare de printare: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index 6c074ed9edce..5acadbc27662 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Рекомендуемые службы"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Отключенные службы"</string>
<string name="all_services_title" msgid="5578662754874906455">"Все службы печати"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтер</item>
+ <item quantity="few">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+ <item quantity="many">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтеров</item>
+ <item quantity="other">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Печать задания \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\"…"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Отмена задания <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ошибка задания \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index 8278aeee4f25..db4c5fdb070e 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"නිර්දේශිත සේවා"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"අබල කළ සේවා"</string>
<string name="all_services_title" msgid="5578662754874906455">"සියලු සේවා"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">මුද්‍රණ යන්ත්‍ර <xliff:g id="COUNT_1">%1$s</xliff:g>ක් සොයා ගැනීමට ස්ථාපනය කරන්න</item>
+ <item quantity="other">මුද්‍රණ යන්ත්‍ර <xliff:g id="COUNT_1">%1$s</xliff:g>ක් සොයා ගැනීමට ස්ථාපනය කරන්න</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> මුද්‍රණය වේ"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"අවලංගු කෙරේ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"මුද්‍රණ දෝෂය <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 610fe99722d3..63ee5e2a59ad 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Odporúčané služby"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Zakázané služby"</string>
<string name="all_services_title" msgid="5578662754874906455">"Všetky služby"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="few">Nainštalujte a objavte <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarne</item>
+ <item quantity="many">Nainštalujte a objavte <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarne</item>
+ <item quantity="other">Nainštalujte a objavte <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarní</item>
+ <item quantity="one">Nainštalujte a objavte <xliff:g id="COUNT_0">%1$s</xliff:g> tlačiareň</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Prebieha tlač úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prebieha zrušenie úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tlačiarne – úloha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index b5124b4d43bc..f7616db5db94 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Priporočene storitve"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Onemogočene storitve"</string>
<string name="all_services_title" msgid="5578662754874906455">"Vse storitve"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnika</item>
+ <item quantity="two">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnikov</item>
+ <item quantity="few">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnikov</item>
+ <item quantity="other">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnikov</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Tiskanje: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Preklic: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Napaka tiskalnika: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sq-rAL/strings.xml b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
index 27bbbf902653..f4d2817f0d22 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Shërbimet e rekomanduara"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Shërbimet e çaktivizuara"</string>
<string name="all_services_title" msgid="5578662754874906455">"Të gjitha shërbimet"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Instaloje për të zbuluar <xliff:g id="COUNT_1">%1$s</xliff:g> printera</item>
+ <item quantity="one">Instaloje për të zbuluar <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Po printon <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Po anulon <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri ndeshi në gabim gjatë punës: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index ea6fcb7a0e9d..b285044fbbfd 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -73,6 +73,11 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Препоручене услуге"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Онемогућене услуге"</string>
<string name="all_services_title" msgid="5578662754874906455">"Све услуге"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Инсталирајте да бисте открили <xliff:g id="COUNT_1">%1$s</xliff:g> штампач</item>
+ <item quantity="few">Инсталирајте да бисте открили <xliff:g id="COUNT_1">%1$s</xliff:g> штампача</item>
+ <item quantity="other">Инсталирајте да бисте открили <xliff:g id="COUNT_1">%1$s</xliff:g> штампача</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Штампа се <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Отказује се <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка штампача <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index c909e19c70ff..4a728006fe05 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Rekommenderade tjänster"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Inaktiverade tjänster"</string>
<string name="all_services_title" msgid="5578662754874906455">"Alla tjänster"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Installera och hitta <xliff:g id="COUNT_1">%1$s</xliff:g> skrivare</item>
+ <item quantity="one">Installera och hitta <xliff:g id="COUNT_0">%1$s</xliff:g> skrivare</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Skriver ut <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Skrivarfel för <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index bd14117def99..34b935d5fd95 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Huduma zinazopendekezwa"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Huduma ambazo haziruhusiwi"</string>
<string name="all_services_title" msgid="5578662754874906455">"Huduma zote"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Sakinisha ili ugundue printa <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ <item quantity="one">Sakinisha ili ugundue printa <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Inachapisha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Inaghairi <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Hitilafu ya kuchapisha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ta-rIN/strings.xml b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
index 782ebf21bf86..22f41bfe7f37 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"பரிந்துரைக்கப்படும் அச்சுப் பொறிகள்"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"முடக்கப்பட்ட அச்சுப் பொறிகள்"</string>
<string name="all_services_title" msgid="5578662754874906455">"எல்லா அச்சுப் பொறிகளும்"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> பிரிண்டர்களைக் கண்டறிய, நிறுவவும்</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> பிரிண்டரைக் கண்டறிய, நிறுவவும்</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ஐ அச்சிடுகிறது"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ஐ ரத்துசெய்கிறது"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"பிரிண்டர் பிழை <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index ca393c839ff2..1211cfdff4c7 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"సిఫార్సు చేయబడిన సేవలు"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"నిలిపివేసిన సేవలు"</string>
<string name="all_services_title" msgid="5578662754874906455">"అన్ని సేవలు"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ప్రింటర్‌లను కనుగొనడానికి ఇన్‌స్టాల్ చేయండి</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> ప్రింటర్‌ను కనుగొనడానికి ఇన్‌స్టాల్ చేయండి</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను ముద్రిస్తోంది"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను రద్దు చేస్తోంది"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ప్రింటర్ లోపం <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index 92b960e67344..7f9928829dcc 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"บริการที่แนะนำ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"บริการที่ปิดใช้"</string>
<string name="all_services_title" msgid="5578662754874906455">"บริการทั้งหมด"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">ติดตั้งเพื่อค้นหาเครื่องพิมพ์ <xliff:g id="COUNT_1">%1$s</xliff:g> เครื่อง</item>
+ <item quantity="one">ติดตั้งเพื่อค้นหาเครื่องพิมพ์ <xliff:g id="COUNT_0">%1$s</xliff:g> เครื่อง</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"กำลังพิมพ์ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"กำลังยกเลิก <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ข้อผิดพลาดเครื่องพิมพ์ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index 5a7365990ead..7b5081509451 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Mga inirerekomendang serbisyo"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Mga naka-disable na serbisyo"</string>
<string name="all_services_title" msgid="5578662754874906455">"Lahat ng serbisyo"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">I-install upang tumuklas ng <xliff:g id="COUNT_1">%1$s</xliff:g> printer</item>
+ <item quantity="other">I-install upang tumuklas ng <xliff:g id="COUNT_1">%1$s</xliff:g> na printer</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Pini-print ang <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kinakansela ang <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error sa printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index f17bc9d2ed73..1ca722b0b758 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Önerilen hizmetler"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Devre dışı bırakılmış hizmetler"</string>
<string name="all_services_title" msgid="5578662754874906455">"Tüm hizmetler"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> yazıcıyı keşfetmek için yükleyin</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> yazıcıyı keşfetmek için yükleyin</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> yazdırılıyor"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> iptal ediliyor"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Yazıcı hatası: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 9629ad396cff..800463966678 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -74,6 +74,12 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Рекомендовані служби"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Вимкнені служби"</string>
<string name="all_services_title" msgid="5578662754874906455">"Усі служби"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтер</item>
+ <item quantity="few">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтери</item>
+ <item quantity="many">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтерів</item>
+ <item quantity="other">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" друкується"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" скасовується"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Помилка завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 0d01ee20e97c..19e759cbc377 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"تجویز کردہ سروسز"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"غیر فعال کردہ سروسز"</string>
<string name="all_services_title" msgid="5578662754874906455">"تمام سروسز"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> پرنٹرز دریافت کرنے کیلئے انسٹال کریں</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> پرنٹر دریافت کرنے کیلئے انسٹال کریں</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> پرنٹ کررہا ہے"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> کو منسوخ کر رہا ہے"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"پرنٹر کی خرابی <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index 1f379d94b6f1..cf87a740d133 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Tavsiya etilgan xizmatlar"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"O‘chirib qo‘yilgan xizmatlar"</string>
<string name="all_services_title" msgid="5578662754874906455">"Barcha xizmatlar"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ta printerni topish uchun o‘rnating</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> ta printerni topish uchun o‘rnating</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Chop etilmoqda: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bekor qilinmoqda"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printerda xatolik: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index b931557178c4..2c1fa2701120 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Dịch vụ được đề xuất"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Dịch vụ đã tắt"</string>
<string name="all_services_title" msgid="5578662754874906455">"Tất cả dịch vụ"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">Cài đặt để phát hiện <xliff:g id="COUNT_1">%1$s</xliff:g> máy in</item>
+ <item quantity="one">Cài đặt để phát hiện <xliff:g id="COUNT_0">%1$s</xliff:g> máy in</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"In <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hủy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Lỗi máy in <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index ffc9f85cbf02..b3500514fa6f 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"推荐的服务"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"已停用的服务"</string>
<string name="all_services_title" msgid="5578662754874906455">"所有服务"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">安装即可找到 <xliff:g id="COUNT_1">%1$s</xliff:g> 台打印机</item>
+ <item quantity="one">安装即可找到 <xliff:g id="COUNT_0">%1$s</xliff:g> 台打印机</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"正在打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"打印机在打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”时出错"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 4411a23b7b76..192b41b06ad5 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"推薦服務"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"已停用的服務"</string>
<string name="all_services_title" msgid="5578662754874906455">"所有服務"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">安裝即可使用 <xliff:g id="COUNT_1">%1$s</xliff:g> 部印表機</item>
+ <item quantity="one">安裝即可使用 <xliff:g id="COUNT_0">%1$s</xliff:g> 部印表機</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"正在列印 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"打印機錯誤:<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 98126a77b489..4aa5681a6035 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"建議的列印服務"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"已停用的列印服務"</string>
<string name="all_services_title" msgid="5578662754874906455">"所有列印服務"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="other">安裝即可使用 <xliff:g id="COUNT_1">%1$s</xliff:g> 個印表機</item>
+ <item quantity="one">安裝即可使用 <xliff:g id="COUNT_0">%1$s</xliff:g> 個印表機</item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"正在列印 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"印表機發生錯誤:<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index f2b49900f0e3..121022b59b1d 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -72,6 +72,10 @@
<string name="recommended_services_title" msgid="3799434882937956924">"Amasevisi anconyiwe"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"Amasevisi akhutshaziwe"</string>
<string name="all_services_title" msgid="5578662754874906455">"Onke amasevisi"</string>
+ <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+ <item quantity="one">Faka ukuze uthole amaphrinta we-<xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ <item quantity="other">Faka ukuze uthole amaphrinta we-<xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ </plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Iphrinta i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ikhansela i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Iphutha lephrinta ye-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index cde0fa3b4896..e7aebddf5aa8 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -62,7 +62,6 @@ import android.printservice.PrintServiceInfo;
import android.provider.DocumentsContract;
import android.text.Editable;
import android.text.TextUtils;
-import android.text.TextUtils.SimpleStringSplitter;
import android.text.TextWatcher;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -117,8 +116,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public class PrintActivity extends Activity implements RemotePrintDocument.UpdateResultCallbacks,
PrintErrorFragment.OnActionListener, PageAdapter.ContentCallbacks,
@@ -165,22 +162,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private static final int MIN_COPIES = 1;
private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);
- private static final Pattern PATTERN_DIGITS = Pattern.compile("[\\d]+");
-
- private static final Pattern PATTERN_ESCAPE_SPECIAL_CHARS = Pattern.compile(
- "(?=[]\\[+&|!(){}^\"~*?:\\\\])");
-
- private static final Pattern PATTERN_PAGE_RANGE = Pattern.compile(
- "[\\s]*[0-9]+[\\-]?[\\s]*[0-9]*[\\s]*?(([,])"
- + "[\\s]*[0-9]+[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*|[\\s]*)+");
-
private boolean mIsOptionsUiBound = false;
private final PrinterAvailabilityDetector mPrinterAvailabilityDetector =
new PrinterAvailabilityDetector();
- private final SimpleStringSplitter mStringCommaSplitter = new SimpleStringSplitter(',');
-
private final OnFocusChangeListener mSelectAllOnFocusListener = new SelectAllOnFocusListener();
private PrintSpoolerProvider mSpoolerProvider;
@@ -1493,9 +1479,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
cancelPrint();
}
} else if (view == mMoreOptionsButton) {
- // The selected pages is only applied once the user leaves the text field. A click
- // on this button, does not count as leaving.
- updateSelectedPagesFromTextField();
+ if (mPageRangeEditText.getError() == null) {
+ // The selected pages is only applied once the user leaves the text field. A click
+ // on this button, does not count as leaving.
+ updateSelectedPagesFromTextField();
+ }
if (mCurrentPrinter != null) {
startAdvancedPrintOptionsActivity(mCurrentPrinter);
@@ -1918,42 +1906,10 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
- List<PageRange> pageRanges = new ArrayList<>();
- mStringCommaSplitter.setString(mPageRangeEditText.getText().toString());
-
- while (mStringCommaSplitter.hasNext()) {
- String range = mStringCommaSplitter.next().trim();
- if (TextUtils.isEmpty(range)) {
- continue;
- }
- final int dashIndex = range.indexOf('-');
- final int fromIndex;
- final int toIndex;
-
- if (dashIndex > 0) {
- fromIndex = Integer.parseInt(range.substring(0, dashIndex).trim()) - 1;
- // It is possible that the dash is at the end since the input
- // verification can has to allow the user to keep entering if
- // this would lead to a valid input. So we handle this.
- if (dashIndex < range.length() - 1) {
- String fromString = range.substring(dashIndex + 1, range.length()).trim();
- toIndex = Integer.parseInt(fromString) - 1;
- } else {
- toIndex = fromIndex;
- }
- } else {
- fromIndex = toIndex = Integer.parseInt(range) - 1;
- }
-
- PageRange pageRange = new PageRange(Math.min(fromIndex, toIndex),
- Math.max(fromIndex, toIndex));
- pageRanges.add(pageRange);
- }
-
- PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
- pageRanges.toArray(pageRangesArray);
+ PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
+ final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
- return PageRangeUtils.normalize(pageRangesArray);
+ return PageRangeUtils.parsePageRanges(mPageRangeEditText.getText(), pageCount);
}
return PageRange.ALL_PAGES_ARRAY;
@@ -2785,7 +2741,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
editText.setSelection(editText.getText().length());
}
- if (view == mPageRangeEditText && !hasFocus) {
+ if (view == mPageRangeEditText && !hasFocus && mPageRangeEditText.getError() == null) {
updateSelectedPagesFromTextField();
}
}
@@ -2805,18 +2761,12 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
@Override
public void afterTextChanged(Editable editable) {
final boolean hadErrors = hasErrors();
- String text = editable.toString();
- if (TextUtils.isEmpty(text)) {
- if (mPageRangeEditText.getError() == null) {
- mPageRangeEditText.setError("");
- updateOptionsUi();
- }
- return;
- }
+ PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
+ final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
+ PageRange[] ranges = PageRangeUtils.parsePageRanges(editable, pageCount);
- String escapedText = PATTERN_ESCAPE_SPECIAL_CHARS.matcher(text).replaceAll("////");
- if (!PATTERN_PAGE_RANGE.matcher(escapedText).matches()) {
+ if (ranges.length == 0) {
if (mPageRangeEditText.getError() == null) {
mPageRangeEditText.setError("");
updateOptionsUi();
@@ -2824,30 +2774,6 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
return;
}
- PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
- final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
-
- // The range
- Matcher matcher = PATTERN_DIGITS.matcher(text);
- while (matcher.find()) {
- String numericString = text.substring(matcher.start(), matcher.end()).trim();
- if (TextUtils.isEmpty(numericString)) {
- continue;
- }
- final int pageIndex = Integer.parseInt(numericString);
- if (pageIndex < 1 || pageIndex > pageCount) {
- if (mPageRangeEditText.getError() == null) {
- mPageRangeEditText.setError("");
- updateOptionsUi();
- }
- return;
- }
- }
-
- // We intentionally do not catch the case of the from page being
- // greater than the to page. When computing the requested pages
- // we just swap them if necessary.
-
if (mPageRangeEditText.getError() != null) {
mPageRangeEditText.setError(null);
updateOptionsUi();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index cee16c8b29e9..fcc9f6a36171 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -18,12 +18,11 @@ package com.android.printspooler.ui;
import android.app.Activity;
import android.app.LoaderManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.content.Loader;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -34,6 +33,7 @@ import android.print.PrinterInfo;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
@@ -80,8 +80,8 @@ public final class SelectPrinterActivity extends Activity implements
private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE";
- /** If there are any enabled print services */
- private boolean mHasEnabledPrintServices;
+ /** The currently enabled print services by their ComponentName */
+ private ArrayMap<ComponentName, PrintServiceInfo> mEnabledPrintServices;
private PrinterRegistry mPrinterRegistry;
@@ -100,6 +100,8 @@ public final class SelectPrinterActivity extends Activity implements
setContentView(R.layout.select_printer_activity);
+ mEnabledPrintServices = new ArrayMap<>();
+
mPrinterRegistry = new PrinterRegistry(this, null, LOADER_ID_PRINT_REGISTRY,
LOADER_ID_PRINT_REGISTRY_INT);
@@ -317,7 +319,7 @@ public final class SelectPrinterActivity extends Activity implements
}
TextView titleView = (TextView) findViewById(R.id.title);
View progressBar = findViewById(R.id.progress_bar);
- if (!mHasEnabledPrintServices) {
+ if (mEnabledPrintServices.size() > 0) {
titleView.setText(R.string.print_no_print_services);
progressBar.setVisibility(View.GONE);
} else if (adapter.getUnfilteredCount() <= 0) {
@@ -346,11 +348,16 @@ public final class SelectPrinterActivity extends Activity implements
@Override
public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
- List<PrintServiceInfo> data) {
- if (data == null || data.isEmpty()) {
- mHasEnabledPrintServices = false;
- } else {
- mHasEnabledPrintServices = true;
+ List<PrintServiceInfo> services) {
+ mEnabledPrintServices.clear();
+
+ if (services != null && !services.isEmpty()) {
+ final int numServices = services.size();
+ for (int i = 0; i < numServices; i++) {
+ PrintServiceInfo service = services.get(i);
+
+ mEnabledPrintServices.put(service.getComponentName(), service);
+ }
}
onPrintServicesUpdate();
@@ -533,14 +540,12 @@ public final class SelectPrinterActivity extends Activity implements
CharSequence title = printer.getName();
Drawable icon = printer.loadIcon(SelectPrinterActivity.this);
- CharSequence printServiceLabel;
- try {
- PackageInfo packageInfo = getPackageManager().getPackageInfo(
- printer.getId().getServiceName().getPackageName(), 0);
+ PrintServiceInfo service = mEnabledPrintServices.get(printer.getId().getServiceName());
- printServiceLabel = packageInfo.applicationInfo.loadLabel(getPackageManager());
- } catch (NameNotFoundException e) {
- printServiceLabel = null;
+ CharSequence printServiceLabel = null;
+ if (service != null) {
+ printServiceLabel = service.getResolveInfo().loadLabel(getPackageManager())
+ .toString();
}
CharSequence description = printer.getDescription();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
index 2b317b3cbef0..7425c033a7a4 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
@@ -18,7 +18,9 @@ package com.android.printspooler.util;
import android.print.PageRange;
import android.print.PrintDocumentInfo;
+import android.util.Pair;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -155,6 +157,167 @@ public final class PageRangeUtils {
}
/**
+ * Return the next position after {@code pos} that is not a space character.
+ *
+ * @param s The string to parse
+ * @param pos The starting position
+ *
+ * @return The position of the first space character
+ */
+ private static int readWhiteSpace(CharSequence s, int pos) {
+ while (pos < s.length() && s.charAt(pos) == ' ') {
+ pos++;
+ }
+
+ return pos;
+ }
+
+ /**
+ * Read a number from a string at a certain position.
+ *
+ * @param s The string to parse
+ * @param pos The starting position
+ *
+ * @return The position after the number + the number read or null if the number was not found
+ */
+ private static Pair<Integer, Integer> readNumber(CharSequence s, int pos) {
+ Integer result = 0;
+ while (pos < s.length() && s.charAt(pos) >= '0' && s.charAt(pos) <= '9') {
+ // Number cannot start with 0
+ if (result == 0 && s.charAt(pos) == '0') {
+ break;
+ }
+ result = result * 10 + (s.charAt(pos) - '0');
+ // Abort on overflow
+ if (result < 0) {
+ break;
+ }
+ pos++;
+ }
+
+ // 0 is not a valid page number
+ if (result == 0) {
+ return new Pair<>(pos, null);
+ } else {
+ return new Pair<>(pos, result);
+ }
+ }
+
+ /**
+ * Read a single character from a string at a certain position.
+ *
+ * @param s The string to parse
+ * @param pos The starting position
+ * @param expectedChar The character to read
+ *
+ * @return The position after the character + the character read or null if the character was
+ * not found
+ */
+ private static Pair<Integer, Character> readChar(CharSequence s, int pos, char expectedChar) {
+ if (pos < s.length() && s.charAt(pos) == expectedChar) {
+ return new Pair<>(pos + 1, expectedChar);
+ } else {
+ return new Pair<>(pos, null);
+ }
+ }
+
+ /**
+ * Read a page range character from a string at a certain position.
+ *
+ * @param s The string to parse
+ * @param pos The starting position
+ * @param maxPageNumber The highest page number to accept.
+ *
+ * @return The position after the page range + the page range read or null if the page range was
+ * not found
+ */
+ private static Pair<Integer, PageRange> readRange(CharSequence s, int pos, int maxPageNumber) {
+ Pair<Integer, Integer> retInt;
+ Pair<Integer, Character> retChar;
+
+ Character comma;
+ if (pos == 0) {
+ // When we reading the first range, we do not want to have a comma
+ comma = ',';
+ } else {
+ retChar = readChar(s, pos, ',');
+ pos = retChar.first;
+ comma = retChar.second;
+ }
+
+ pos = readWhiteSpace(s, pos);
+
+ retInt = readNumber(s, pos);
+ pos = retInt.first;
+ Integer start = retInt.second;
+
+ pos = readWhiteSpace(s, pos);
+
+ retChar = readChar(s, pos, '-');
+ pos = retChar.first;
+ Character separator = retChar.second;
+
+ pos = readWhiteSpace(s, pos);
+
+ retInt = readNumber(s, pos);
+ pos = retInt.first;
+ Integer end = retInt.second;
+
+ pos = readWhiteSpace(s, pos);
+
+ if (comma != null &&
+ // range, maybe unbounded
+ ((separator != null && (start != null || end != null)) ||
+ // single page
+ (separator == null && start != null && end == null))) {
+ if (start == null) {
+ start = 1;
+ }
+
+ if (end == null) {
+ if (separator == null) {
+ end = start;
+ } else {
+ end = maxPageNumber;
+ }
+ }
+
+ if (start <= end && start >= 1 && end <= maxPageNumber) {
+ return new Pair<>(pos, new PageRange(start - 1, end - 1));
+ }
+ }
+
+ return new Pair<>(pos, null);
+ }
+
+ /**
+ * Parse a string into an array of page ranges.
+ *
+ * @param s The string to parse
+ * @param maxPageNumber The highest page number to accept.
+ *
+ * @return The parsed ranges or null if the string could not be parsed.
+ */
+ public static PageRange[] parsePageRanges(CharSequence s, int maxPageNumber) {
+ ArrayList<PageRange> ranges = new ArrayList<>();
+
+ int pos = 0;
+ while (pos < s.length()) {
+ Pair<Integer, PageRange> retRange = readRange(s, pos, maxPageNumber);
+
+ if (retRange.second == null) {
+ ranges.clear();
+ break;
+ }
+
+ ranges.add(retRange.second);
+ pos = retRange.first;
+ }
+
+ return PageRangeUtils.normalize(ranges.toArray(new PageRange[ranges.size()]));
+ }
+
+ /**
* Offsets a the start and end of page ranges with the given value.
*
* @param pageRanges The page ranges to offset.
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 9cf9dc979c2a..c44f0d06bd65 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – sowat <xliff:g id="TIME">%2$s</xliff:g> oor"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol op WS"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol oor USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol vanaf draadloos"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laai tans op WS"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laai tans oor USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laai tans draadloos"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Laai nie"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laai nie"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Vol"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 40e5a31c87fc..cd05135def5c 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ይህ ባህሪ የሙከራ ነውና አፈጻጸም ላይ ተጽዕኖ ሊኖረው ይችላል።"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> ገደማ ቀርቷል"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ገደማ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> እስከሚሞላ ድረስ"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በኤሲ ላይ እስከሚሞላ ድረስ"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በዩኤስቢ ላይ እስከሚሞላ ድረስ"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በገመድ አልባ ላይ እስከሚሞላ ድረስ"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"ያልታወቀ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"በኤሲ ሃይል በመሙላት ላይ"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"በዩኤስቢ ሃይል በመሙላት ላይ"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"በገመድ አልባ ሃይል በመሙላት ላይ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ባትሪ እየሞላ አይደለም"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ኃይል እየሞላ አይደለም"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ሙሉነው"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index e21b02c706df..b3f55eb03fd1 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"هذه الميزة تجريبية وقد تؤثر في الأداء."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> تقريبًا"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال باستخدام التيار المتردد"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"‏<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال عبر USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال بالشحن اللاسلكي"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"غير معروف"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"شحن"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"جارٍ الشحن بتيار متردد"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏جارٍ الشحن عبر USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"جارٍ الشحن لاسلكيًا"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"لا يتم الشحن"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"لا يتم الشحن"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ممتلئة"</string>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index ca06e664fca9..9a099aff3a7f 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> dolana qədər"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC üzərindən dolana qədər"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB üzərindən dolana qədər"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> naqilsiz üzərindən dolana qədər"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Dəyişən cərəyanda qidalanır"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB üzərindən qidalanır"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Naqilsiz qidalanır"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Doldurulmur"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Enerji doldurulmur"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Tam"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 4bd9b0381cac..85b6ac2fb13b 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo oko <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni punjačem"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni preko USB-a"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni bežično"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Punjenje preko punjača"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index ebb5a592a75e..c8098ec22300 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -278,7 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Запусціць апрацоўшчыкі WebView у ізаляваным працэсе."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Рэалізацыя WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Наладзіць рэалізацыю WebView"</string>
- <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Гэты элемент больш не даступны для выбару. Паспрабуйце яшчэ раз."</string>
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Гэты варыянт больш не даступны. Паспрабуйце яшчэ раз."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Перайсці на шыфраванне файлаў"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Пераход..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Шыфраванне файлаў ужо дзейнічае"</string>
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Гэтая функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Засталося прыблізна <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося прыблізна <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі ад сеткі пер. току"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі па USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўн. зарадкі бесправадным шляхам"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Невядома"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарадка"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зар. ад сеткі пер. току"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарадка па USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бесправадная зарадка"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не зараджаецца"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не зараджаецца"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Поўная"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index e0641b1b45ac..35b24bf23129 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Прибл. оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – приблизително оставащо време: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане при променлив ток"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> ˜– <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане през USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно безжично зареждане"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарежда се"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зареждане при AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зареждане през USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично зареждане"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не се зарежда"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се зарежда"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Пълна"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 5ca7d033ccac..14c2c9549fc5 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -296,17 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং এটি কার্য-সম্পাদনা প্রভাবিত করতে পারে।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"প্রায় <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - আনুমানিক <xliff:g id="TIME">%2$s</xliff:g> বাকি আছে"</string>
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ACতে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB এর মাধ্যমে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেতার যোগে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"অজানা"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC তে চার্জ হচ্ছে"</string>
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB এর মাধ্যমে চার্জ হচ্ছে"</string>
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"তারবিহীনভাবে চার্জ হচ্ছে"</string>
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"চার্জ হচ্ছে না"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"চার্জ হচ্ছে না"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"পূর্ণ"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index ce0f40994906..f9c7fcad3907 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna te može utjecati na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo vreme je otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja na el. napajanju"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije preko USB-a"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije bežičnim punjenjem"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Puni se"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Puni se na punjaču"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5106f5bd4f77..a07074071b55 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -296,17 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Aquesta funció és experimental i pot afectar el rendiment."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Temps restant aproximat: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: falten aproximadament <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g>; temps restant: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega per CA"</string>
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega per USB"</string>
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega sense fil"</string>
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Càrrega: corr. alt."</string>
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"S\'està carregant"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Càrrega per USB"</string>
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"S\'està carregant"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Càrrega sense fils"</string>
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"S\'està carregant"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"No s\'està carregant"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 3d3dd6fb1877..040c9f06255f 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g> (přibližně)"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá přibližně <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití ze zásuvky"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití přes USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití bezdrátově"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjení z adaptéru"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjení přes USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrátové nabíjení"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíjí se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíjí se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 1f354b7f1bea..ddad673dfc86 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -296,17 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string>
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string>
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet"</string>
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med adapter"</string>
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med USB"</string>
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med trådløs"</string>
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Opladning med AC"</string>
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Oplader"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladning via USB"</string>
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Oplader"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Trådløs opladning"</string>
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Oplader"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"Oplader ikke"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Oplader ikke"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fuld"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 404b72b24dc8..514228faea41 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierbei handelt es sich um eine experimentelle Funktion. Dies kann sich auf die Leistung auswirken."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g> verbleibend"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch etwa <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei Stromanschluss voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – über USB voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei kabellosem Laden voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laden über Netzteil"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laden über USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kabelloses Laden"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Wird nicht geladen"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wird nicht geladen"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Voll"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 52988f67741b..8df693ae3b54 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Αυτή η λειτουργία είναι πειραματική και ενδεχομένως να επηρεάσει τις επιδόσεις."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Απομένουν περίπου <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - απομένουν περίπου <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση με φορτιστή AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση μέσω USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη ασύρματη φόρτιση"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Άγνωστο"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Φόρτιση"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Φόρτιση με AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Φόρτιση μέσω USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ασύρματη φόρτιση"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Δεν φορτίζει"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Δεν φορτίζει"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Πλήρης"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index b2df062b6f11..466291aff7ff 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index b2df062b6f11..466291aff7ff 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index b2df062b6f11..466291aff7ff 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index dd7ee4d6823d..9bc2cf414d25 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Falta <xliff:g id="TIME">%1$s</xliff:g> aproximadamente"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: alrededor de <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por CA"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga inalámbrica"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carga en CA"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carga con USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carga inalámbrica"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando."</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se realiza la carga"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Cargado"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 0cc6cb6fa83c..ec0cafea2792 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -34,7 +34,7 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string>
<string name="wifi_connected_no_internet" msgid="3149853966840874992">"Conexión sin Internet"</string>
- <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectada"</string>
+ <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
<string name="bluetooth_connecting" msgid="8555009514614320497">"Estableciendo conexión…"</string>
<string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string>
@@ -296,17 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar al rendimiento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Tiempo restante (aproximado): <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quedan <xliff:g id="TIME">%2$s</xliff:g> aproximadamente"</string>
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tiempo restante: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería"</string>
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería con CA"</string>
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería por USB"</string>
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería con Wi-Fi"</string>
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Cargando en CA"</string>
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Cargando"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string>
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Cargando"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando de forma inalámbrica"</string>
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Cargando"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se está cargando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index a275b1a8c9af..29a1aea1e20d 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"See funktsioon on katseline ja võib mõjutada toimivust."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Umbes <xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – jäänud on umbes <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (vahelduvvool)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (USB)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (juhtmeta laad.)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laad. vahelduvv.-v."</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laadimine USB kaudu"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Juhtmevaba laadimine"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ei lae"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei lae"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Täis"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 2556224e0dce..4f55e350fbe0 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> inguru guztiz kargatu arte"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> inguru. <xliff:g id="TIME">%2$s</xliff:g> geratzen d(ir)a"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> korrontearen bidez guztiz kargatu arte"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB bidez guztiz kargatu arte"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> haririk gabe guztiz kargatu arte"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzea"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"KA bidez kargatzen"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB bidez kargatzen"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hari gabe kargatzen"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ez da kargatzen ari"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ez da kargatzen ari"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Beteta"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 1e67182a4bda..e9d63fddd521 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"این قابلیت آزمایشی است و ممکن است عملکرد را تحت تأثیر قرار دهد."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> باقی مانده است"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً ‏<xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل با جریان متناوب"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"‏<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل از طریق USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل به‌طور بی‌سیم"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"ناشناس"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"در حال شارژ شدن"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"شارژ با جریان متناوب"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏شارژ از طریق USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"شارژ به صورت بی‌سیم"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"شارژ نمی‌شود"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"شارژ نمی‌شود"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"پر"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 3d8ac9887163..5531d270e1f3 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (laturilataus)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (USB-lataus)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (WiFi-lataus)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laturilataus"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-lataus"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Langaton lataus"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ei laturissa"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei laturissa"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Täynnä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 4eb3a427d0d4..df6bdc64b394 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut toucher les performances."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> %% – Temps restant : environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (charge complète sur c.a. dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% par USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% avec chargeur sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge (c.a.)"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge par USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"N\'est pas en charge"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"N\'est pas en charge"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Pleine"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index efb10ecedeb6..ee40b2a42ff2 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>."</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <xliff:g id="TIME">%2$s</xliff:g> environ"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sur secteur dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% via USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge sur secteur"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge via USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Pas en charge"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Débranchée"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 3d61e215208c..4a0451e42aad 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Duración aproximada de <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - faltan aproximadamente <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con CA"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga co modo sen fíos"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Cargando con CA"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando sen fíos"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Non se está cargando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non está cargando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 628b4be81c46..becda2852f46 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"અંદાજે. <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - આશરે <xliff:g id="TIME">%2$s</xliff:g> બાકી"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"સંપૂર્ણ થવામાં <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>, AC પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>, USB પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> વાયરલેસ દ્વારા પૂર્ણ થાય ત્યાં સુધી"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC પર ચાર્જિંગ"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB થી ચાર્જિંગ"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"વાયરલેસથી ચાર્જિંગ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ચાર્જ થઈ રહ્યું નથી"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ચાર્જ થઈ રહ્યું નથી"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"પૂર્ણ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 047c7db08f80..6dffdd9d7269 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यह सुविधा प्रायोगिक है और निष्पादन को प्रभावित कर सकती है."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग <xliff:g id="TIME">%2$s</xliff:g> शेष"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूरी होने तक"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC पर पूरी होने तक"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB पर पूरी होने तक"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेस से पूरी होने तक"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हो रही है"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC से चार्ज हो रही"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB पर चार्ज हो रही"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस रूप से चार्ज हो रही"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज नहीं हो रही है"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज नहीं हो रही है"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"पूरी"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f5ad6d2323a1..1edb01544831 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -296,17 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova je značajka eksperimentalna i može utjecati na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Još približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Još <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – još približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – još <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string>
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti strujnim napajanjem"</string>
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti putem USB-a"</string>
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti bežičnim putem"</string>
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Punjenje punjačem"</string>
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Punjenje"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje putem USB-a"</string>
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Punjenje"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Punjenje"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 7279c9cfc2f8..060599cfa10e 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -296,17 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Kb. <xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – kb. <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttség eléréséig"</string>
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig hálózatról"</string>
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig USB-ről"</string>
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig vezeték nélkül"</string>
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Ismeretlen"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Töltés"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Hálózati töltés"</string>
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Töltés"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-s töltés"</string>
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Töltés"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Nem vezetékes töltés"</string>
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Töltés"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nem tölt"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nem töltődik"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Feltöltve"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 23d83a272ce4..63c433668aea 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել աշխատանքի վրա:"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - մնաց մոտավորապես <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը հոսանքից"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը USB-ով"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը անլար ցանցից"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Անհայտ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Լիցքավորում"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Լիցքավորում AC-ով"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Լիցքավորում USB-ով"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Անլար լիցքավորում"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Չի լիցքավորվում"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Չի լիցքավորվում"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Լիցքավորված"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 24fd0f17c4b9..c86c76842eaa 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira tersisa <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira tersisa. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh pada AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh melalui USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh dari nirkabel"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengisi daya pada AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Isi daya lewat USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Isi daya nirkabel"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengisi daya"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengisi daya"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index e22dbe036782..1fc0dc0763da 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu með hleðslutæki"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu í gegnum USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu þráðlaust"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Hleðslutæki tengt"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Hleður um USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hleður þráðlaust"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ekki í hleðslu"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ekki í hleðslu"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fullhlaðin"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 84ff78a4a21c..78cd29b854b0 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Circa <xliff:g id="TIME">%1$s</xliff:g> rimanenti"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tempo rimanente: <xliff:g id="TIME">%2$s</xliff:g> circa"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite CA"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lla carica completa con wireless"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"In carica tramite CA"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"In carica tramite USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"In carica, wireless"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Non in carica"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non in carica"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Carica"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 74ea37200f52..16e0f44d8e6f 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"נשארו <xliff:g id="TIME">%1$s</xliff:g> בערך"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> בקירוב עד לסיום"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>‏ - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בזרם חילופין"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"‏<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי ב-USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בטעינה אלחוטית"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"טוען"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"טוען בזרם חילופין"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏טוען ב-USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"טוען באופן אלחוטי"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"לא בטעינה"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"לא טוען"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"מלא"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 2556d994c469..ce405dffd86a 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"この機能は試験運用機能であり、パフォーマンスに影響することがあります。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"あと約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り約<xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(AC)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(USB)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(ワイヤレス)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACで充電しています"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBで充電しています"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"無線で充電しています"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"充電していません"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"充電していません"</string>
<!-- String.format failed for translation -->
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 29e9459e241b..20a1d2a351ae 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს შესრულებაზე."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"დარჩენილია დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"დაახლ. <xliff:g id="LEVEL">%1$s</xliff:g> დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> სრულ დატენვამდე"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ელკვებით სრულ დატენვამდე"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB-თი სრულ დატენვამდე"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> უსადენოდან სრულ დატენვამდე"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"უცნობი"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"იტენება"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"დატენვა ელკვებაზე"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"დატენვა USB-ზე"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"დატენვა უსადენოდ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"არ იტენება"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"არ იტენება"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ბატარეა დატენილია"</string>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index fdd3f955e930..e71c8d0ca6d4 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бұл мүмкіндік эксперименттік болып табылады және өнімділікке әсер етуі мүмкін."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - айнымалы токпен толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB арқылы толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - сымсыз толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Белгісіз"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядталуда"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Айнымалы токпен зар."</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB арқылы зарядтау"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Сымсыз зарядтау"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Зарядталу орындалып жатқан жоқ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Зарядталып тұрған жоқ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Толық"</string>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 2cafa294f00e..687b71b17ade 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"លក្ខណៈ​នេះ​គឺ​ជា​ការ​ពិសោធន៍ ហើយ​អាច​ប៉ះពាល់​ការ​អនុវត្ត។"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"បដិសេធ​ដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"នៅសល់ប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅ​សល់​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់​ពេញ"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់ពេញ​រចន្ត​ឆ្លាស់"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់​ពេញ​តាមយូអេសប៊ី"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់​ពេញ​ពី​ឥតខ្សែ"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"មិន​ស្គាល់"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"កំពុងបញ្ចូល​ថ្ម"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"បញ្ចូលថ្មតាម AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"បញ្ចូលថ្មតាមយូអេសប៊ី"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"បញ្ចូលថ្មដោយ​​ឥតខ្សែ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"មិនកំពុង​បញ្ចូល​ថ្ម"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"មិន​បញ្ចូលថ្ម"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ពេញ"</string>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 6d13b354d8c0..713d9b3a73af 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"ಸುಮಾರು <xliff:g id="TIME">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"ಸುಮಾರು <xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ನಲ್ಲಿ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ಮೂಲಕ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ವೈರ್‌‌ಲೆಸ್‌ನಿಂದ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"ಅಜ್ಞಾತ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ನಲ್ಲಿ ಚಾರ್ಜ್‌"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ಮೂಲಕ ಚಾರ್ಜ್‌"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ನಿಸ್ತಂತುವಾಗಿ ಚಾರ್ಜ್‌"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ಚಾರ್ಜ್‌ ಆಗುತ್ತಿಲ್ಲ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ಭರ್ತಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 035793ec0930..348141ed75ca 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"실험실 기능이며 성능에 영향을 줄 수 있습니다."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"약 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 대략 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(AC 전원)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(USB)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(무선)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"알 수 없음"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"충전 중"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"충전 중(AC 전원)"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"충전 중(USB)"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"충전 중(무선)"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"충전 안함"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"충전 안함"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"충전 완료"</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 8c43312c34d1..2016f0497820 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бул сынамык мүмкүнчүлүк болгондуктан, иштин майнаптуулугуна таасир этиши мүмкүн."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> калды"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - болжол менен <xliff:g id="TIME">%2$s</xliff:g> саат калды"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> толгончо"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC аркылуу толгончо"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB аркылуу толгончо"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> зымсыз кубаттоо аркылуу толгончо"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Белгисиз"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Кубатталууда"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ӨА кубатталууда"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB\'ден кубатталууда"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Зымсыз кубатталууда"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Кубат алган жок"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Кубатталган жок"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Толук"</string>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index f158d44dadcf..7e6db5ee29b6 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"​ຄຸນ​ສົມ​ບັດ​ນີ້​ກຳ​ລັງ​ຢູ່​ໃນ​ການ​ທົດ​ລອງ​ແລະ​ອາດ​ມີ​ຜົນ​ຕໍ່​ປະ​ສິດ​ທິ​ພາບ."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"ຍັງເຫຼືອປະມານ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ​ເຫຼືອປະ​ມານ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງ​ຈະ​ເຕັມ"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ​ຈຶ່ງ​ຈະ​ເຕັມ​ໂດຍສາກ​ດ້ວຍ​ໄຟ AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງ​ຈະ​ເຕັມ​ໂດຍສາກ​ດ້ວຍ USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ​ຈຶ່ງ​ຈະ​ເຕັມ​ໂດຍ​ສາກ​ແບບ​ໄຮ້​ສາຍ"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"ບໍ່ຮູ້ຈັກ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ກຳ​​ລັງ​ສາກ​ຜ່ານ​ໝໍ້​ໄຟ"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"ກຳ​ລັງ​ສາກ​ຜ່ານ USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ກຳ​ລັງ​ສາກ​ໄຮ້​ສາຍ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ບໍ່ໄດ້ສາກໄຟ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ບໍ່ໄດ້ສາກໄຟ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ເຕັມ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index d5cea8efc460..d49876e69b16 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naud. kint. sr."</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naudojant USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo belaid. ryš."</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Įkr. naud. kint. sr."</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Įkraunama naud. USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Įkraunama be laidų"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nekraunama"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nekraunama"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Visiškai įkrautas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index ea6f4f9627e8..6cd9cfd5da38 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> — aptuvenais atlikušais laiks: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai maiņstrāvas uzlādei"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai USB uzlādei"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai bezvadu uzlādei"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Maiņstrāvas uzlāde"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB uzlāde"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezvadu uzlāde"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nenotiek uzlāde"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenotiek uzlāde"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Pilns"</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index e954cdf12bb6..f8f65ec8bd52 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Функцијата е експериментална и може да влијае на изведбата."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Преостанаа прибл. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостанува приближно <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна на AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна преку USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна, безжично"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Полнење на струја"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Полнење преку УСБ"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично полнење"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не се полни"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се полни"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Целосна"</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index a4b3877bfe01..7350b7fe10a0 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ഈ ഫീച്ചർ പരീക്ഷണാത്മകമായതിനാൽ പ്രകടനത്തെ ബാധിച്ചേക്കാം."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - AC-യിൽ പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - വയർലെസ് വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"അജ്ഞാതം"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ചാർജ്ജുചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-യിൽ ചാർജ്ജുചെയ്യുന്നു"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-യിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"വയർലെസ്സ് കണക്ഷനിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"നിറഞ്ഞു"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index d989ef86d7dc..7eeae06da0c0 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Энэ функц туршилтынх бөгөөд ажиллагаанд нөлөөлж болзошгүй."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"АС-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"USB-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"утасгүй цэнэглэгчээр дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Тодорхойгүй"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Цэнэглэж байна"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-р цэнэглэж байна"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-р цэнэглэж байна"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Кабльгүйгээр цэнэглэж байна"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Цэнэглэхгүй байна"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Цэнэглэхгүй байна"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Дүүрэн"</string>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index d363874ae69b..0521ba1a888d 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"हे वैशिष्‍ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"अंदाजे. <xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - अंदाजे. <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण होण्यात"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC वरून पूर्ण होण्यात"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB वरून पूर्ण होण्यात"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसवरून पूर्ण होण्यात"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC वर चार्ज करीत आहे"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB वरून चार्ज करीत आहे"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस वरून चार्ज करीत आहे"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज होत नाही"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज होत नाही"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index ea79a468bbc2..a8be0e5b9791 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira. <xliff:g id="TIME">%2$s</xliff:g> yang tinggal"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh di AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh melalui USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh dari wayarles"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengecas pada AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Mengecas melalui USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Mengecas tanpa wayar"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengecas"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengecas"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 74e0f29b809f..220deffc42f3 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ဒီအင်္ဂါရပ်မှာ စမ်းသပ်မှု ဖြစ်၍ လုပ်ကိုင်မှုကို အကျိုးသက်ရောက်နိုင်သည်။"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"ခန့်မှန်းခြေ <xliff:g id="TIME">%1$s</xliff:g> ကျန်ပါသည်"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ခန့်မှန်းခြေ။ <xliff:g id="TIME">%2$s</xliff:g> ကျန်ရှိနေ"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> အပြည့်အထိ"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> လျှပ်စစ်ဖြင့် အပြည့်အထိ"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ဖြင့် အပြည့်အထိ"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ကြိုးမဲ့ဖြင့် အပြည့်အထိ"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"အကြောင်းအရာ မသိရှိ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"အားသွင်းနေပါသည်"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"လျှပ်စစ်ဖြင့် အားသွင်းနေ"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBဖြင့် အားသွင်းနေ"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ကြိုးမဲ့ အားသွင်းနေ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"အားသွင်းမနေပါ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"အားသွင်းမနေပါ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"အပြည့်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 1a0b4683fc82..a1407ace2d00 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funksjonen er eksperimentell og kan påvirke ytelsen."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> igjen"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> med vekselstrøm"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via trådløs lading"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Lader via strømuttak"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Lader via USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Lader trådløst"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Lader ikke"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Lader ikke"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index a001cab2651f..83e2e74a3b40 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी छ"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग। <xliff:g id="TIME">%2$s</xliff:g> बायाँ"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण नभए सम्म"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC मा पूर्ण नभए सम्म"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB मा पूर्ण नभए सम्म"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसबाट पूर्ण नभए सम्म"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC मा चार्ज गर्दै"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB मा चार्ज गर्दै"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"बिना तार चार्ज गर्दै"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज भइरहेको छैन"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज हुँदै छैन"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 301e3276a5f5..55017d837cc5 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> resterend"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ca. <xliff:g id="TIME">%2$s</xliff:g> resterend"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via wisselstroom"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via draadloos"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Opladen via netvoeding"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladen via USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Draadloos opladen"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Wordt niet opgeladen"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wordt niet opgeladen"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Volledig"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index c792ec93834c..eb1eaacfbc8f 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਪੂਰੀ ਹੋਣ ਤੱਕ"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਵਾਇਰਲੈਸ ਤੋਂ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜਿੰਗ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ਤੇ ਚਾਰਜਿੰਗ"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ਤੇ ਚਾਰਜਿੰਗ"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ਵਾਇਰਲੈਸ ਤੌਰ ਤੇ ਚਾਰਜਿੰਗ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ਪੂਰੀ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 8aad98b140a7..1e56cfd07b32 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Pozostało około <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostało ok. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania z gniazdka"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania przez USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania bezprzewodowo"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Ładowanie zasilaczem"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Ładowanie przez USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ład. bezprzewodowe"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nie podłączony"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nie podłączony"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Naładowana"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index c05458bc4998..93f333aa9d2e 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 402bc860a7b7..dda00fe91287 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta funcionalidade é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Resta(m) aproximadamente <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) aprox. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de CA"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até ficar compl. por rede s/ fios"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"A carregar por CA"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"A carregar por USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"A carregar sem fios"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Não está a carregar"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está a carregar"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Completo"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index c05458bc4998..93f333aa9d2e 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index d5e07690382b..3c46d4142e4f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – timp rămas: aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă la c.a."</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă prin USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă wireless"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Încarcă"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Se încarcă la C.A."</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Se încarcă prin USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Se încarcă fără fir"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nu se încarcă"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nu încarcă"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Complet"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 7ad9f160d70e..f4929de01bc2 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Это экспериментальная функция, она может снизить производительность устройства."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Осталось примерно <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – осталось около <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (от сети)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (через USB)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (беспроводная)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Идет зарядка"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зарядка от сети"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарядка через USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Беспроводная зарядка"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряжается"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряжается"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Батарея заряжена"</string>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 4c73219f95e4..99f018bbdc5e 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්‍රියාකාරිත්වයට බලපෑ හැක."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"දළ වශයෙන් <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරිය"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආසන්න <xliff:g id="TIME">%2$s</xliff:g> වම"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"AC හි <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"USB හරහ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"රේඩියෝව වෙතින් <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පූර්ණ වන තෙක්"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC හි ආරෝපණය වෙමින්"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB හරහා ආරෝපණය වෙමින්"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"රැහැන් රහිතව ආරෝපණය වෙමින්"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ආරෝපණය නොවේ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ආරෝපණය නොවෙමින්"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"පූර්ණ"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index e5c9805fc5ae..4dffdefe6064 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Zostáva cca. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva približne <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia zo zásuvky"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia cez USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia bezdrôtovo"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjanie"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjanie zo zásuvky"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjanie cez USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrôtové nabíjanie"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíja sa"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíja sa"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 8257e3c76e48..676a3ab20331 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Še približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek napajalnika"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek USB-ja"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek brezž. pol."</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Polnj. prek iz. toka"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Polnj. prek USB-ja"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Brezžično polnjenje"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Se ne polni"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Se ne polni"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Poln"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 4a673480d095..c18e63950e79 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Afërsisht <xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - afërsisht <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të jetë e plotë"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet në AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet me USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet nga lidhja pa tel"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Po ngarkohet"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Po ngarkohet në AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Po ngarkohet me USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Po ngarkohet me valë"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nuk po ngarkohet"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nuk po ngarkohet"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"E mbushur"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index eaf7ac5464f7..c0791fcf1a5c 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на перформансе."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Још отприлике <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало око <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни пуњачем"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни преко USB-а"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни бежично"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Пуњење"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Пуњење преко пуњача"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Пуњење преко USB-а"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бежично пуњење"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не пуни се"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не пуни се"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Пуно"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index b01967260807..60c42a53c98f 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca <xliff:g id="TIME">%1$s</xliff:g> kvar"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca <xliff:g id="TIME">%2$s</xliff:g> kvar"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via laddare"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via trådlös laddning"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laddas via adapter"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laddas via USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laddas trådlöst"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Laddar inte"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laddar inte"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 3daa90f70ad8..5de7686e0067 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takriban <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>%% - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa isiyotumia waya"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Inachaji kupitia AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Inachaji kupitia USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Inachaji bila kutumia waya"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Haichaji"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Haichaji"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Imejaa"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 574d105fdd50..a5f04d090291 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"இது சோதனை முறையிலான அம்சம், இது செயல்திறனைப் பாதிக்கலாம்."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"தோராயமாக <xliff:g id="TIME">%1$s</xliff:g> உள்ளது"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"தோராயம்: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> உள்ளது"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"முழு சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"முழு AC சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"முழு USB சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"முழு வயர்லெஸ் சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"அறியப்படாத"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"சார்ஜ் ஏற்றப்படுகிறது"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC மூலம் சார்ஜாகிறது"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB மூலம் சார்ஜாகிறது"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"வயர்லெஸில் சார்ஜாகிறது"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"சார்ஜ் செய்யப்படவில்லை"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"சார்ஜ் ஏறவில்லை"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"முழுமை"</string>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 238911264f47..fe40766aa36e 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"సుమారు <xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - సుమారు <xliff:g id="TIME">%2$s</xliff:g> మిగిలి ఉంది"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ACలో పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB ద్వారా పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - వైర్‌లెస్ నుండి పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACలో ఛార్జ్ అవుతోంది"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ద్వారా ఛార్జ్ అవుతోంది"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"వైర్‌లెస్‌ ద్వారా ఛార్జ్ అవుతోంది"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ఛార్జ్ కావడం లేదు"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ఛార్జ్ కావడం లేదు"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"నిండింది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 0f6f78cb2417..c58692f46411 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"คุณลักษณะนี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"เหลืออีกประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือประมาณ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็ม"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่านระบบไร้สาย"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"ไม่ทราบ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"กำลังชาร์จ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"กำลังชาร์จไฟ AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"กำลังชาร์จผ่าน USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"กำลังชาร์จแบบไร้สาย"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"ไม่ได้ชาร์จ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ไม่ได้ชาร์จ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"เต็ม"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index ef3dde79a0dd..093256c6ef3c 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa pagganap."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> na lang ang natitira"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno mula sa wireless"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nagcha-charge sa AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nagcha-charge sa USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Wireless nag-charge"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Hindi nagcha-charge"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hindi nagkakarga"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 4b7490d700f0..1947d39776a1 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - prize takılı, tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB üzerinden şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - kablosuzdan tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ile şarj oluyor"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ile şarj oluyor"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kablosuz şarj oluyor"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Şarj olmuyor"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Şarj etmiyor"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Dolu"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 5e044c3b2839..0ed6cc0b93ad 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Це експериментальна функція. Вона може вплинути на продуктивність."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Залишилося приблизно <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилось близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження з розетки"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження через USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного з бездротового зарядження"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Невідомо"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядж-ся"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Заряджання з розетки"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Заряджання через USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Заряджання без дроту"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряджається"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряджається"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Акумулятор заряджено"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 6d3c6c4c037f..99a0f2becfcf 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریبا <xliff:g id="TIME">%1$s</xliff:g> باقی ہیں"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎ - تقریبا <xliff:g id="TIME">%2$s</xliff:g> باقی"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>‎"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>‎ پورا ہونے تک"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC‎ پر پورا ہونے تک"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB‎ پر پورا ہونے تک"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>‎ وائرلیس سے پورا ہونے تک"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"‏AC پر چارج ہو رہی ہے"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏‫USB پر چارج ہورہی ہے"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"وائرلیس چارجنگ"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"چارج نہیں ہو رہا ہے"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"چارج نہیں ہو رہا ہے"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"مکمل"</string>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index ec04120f9f03..b9c024351fd9 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, to‘lguncha"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, o‘zgaruvchan tok orqali to‘lguncha"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, USB orqali to‘lguncha"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, simsiz quvvatlash orqali to‘lguncha"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Quvvat olmoqda (AC)"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Quvvat olmoqda (USB)"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Simsiz quvvat olmoqda"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Quvvat olmayapti"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Quvvatlanmayapti"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index dd1d482c4ca0..0c3dc899ce32 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy khi cắm vào nguồn AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy qua USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy từ không dây"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Sạc trên AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Sạc qua USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Sạc không dây"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Hiện không sạc"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hiện không sạc"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Đầy"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 4117ae143f84..2b8ce652fc93 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"此功能为实验性功能,可能会影响性能。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"还剩大约 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还可用大约<xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(交流电充电)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(USB充电)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(无线充电)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"正在充电"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在通过交流电源充电"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在通过USB充电"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在无线充电"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"未在充电"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"未在充电"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"电量充足"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 1fb4c5ea7f49..8dd0417846d1 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會影響效能。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"尚餘大約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 尚餘大約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過插頭充電)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過 USB 充電)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (無線充電)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 充電"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"未開始充電"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"電量已滿"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 9c85f0e54952..dd59954d3ffa 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會對效能造成影響。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"還剩大約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 大約還剩 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (AC)"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (USB)"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (無線充電)"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 變壓器充電"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"非充電中"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"電力充足"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 6017d68bfb37..610cac477886 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -296,17 +296,35 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Cishe ngu-<xliff:g id="TIME">%1$s</xliff:g> osele"</string>
+ <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+ <skip />
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - isilinganiso esingu-<xliff:g id="TIME">%2$s</xliff:g> esisele"</string>
+ <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+ <skip />
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale"</string>
+ <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+ <skip />
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ku-AC"</string>
+ <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+ <skip />
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ngaphezulu kwe-USB"</string>
+ <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+ <skip />
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale kusukela kokungenantambo"</string>
+ <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Iyashaja ku-AC"</string>
+ <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+ <skip />
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Iyashaja ngaphezulu kwe-USB"</string>
+ <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+ <skip />
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Iyashaja ngaphandle kwentambo"</string>
+ <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+ <skip />
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ayishaji"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ayishaji"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Kugcwele"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index fe3ef1a9b76b..a560e3c52107 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -733,25 +733,44 @@
<!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging/discharging -->
<string name="power_remaining_duration_only">Approx. <xliff:g id="time">%1$s</xliff:g> left</string>
+ <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging -->
+ <string name="power_remaining_duration_only_short"><xliff:g id="time">%1$s</xliff:g> left</string>
+
<!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
<string name="power_discharging_duration"><xliff:g id="level">%1$s</xliff:g>
- approx. <xliff:g id="time">%2$s</xliff:g> left</string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
+ <string name="power_discharging_duration_short"><xliff:g id="level">%1$s</xliff:g>
+ - <xliff:g id="time">%2$s</xliff:g> left</string>
+
<!-- [CHAR_LIMIT=40] Label for battery level chart when charging -->
<string name="power_charging"><xliff:g id="level">%1$s</xliff:g> -
<xliff:g id="state">%2$s</xliff:g></string>
<!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
<string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> -
<xliff:g id="time">%2$s</xliff:g> until full</string>
+ <!-- [CHAR_LIMIT=40] Short label for battery level chart when charging with duration -->
+ <string name="power_charging_duration_short"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g></string>
<!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
<string name="power_charging_duration_ac"><xliff:g id="level">%1$s</xliff:g> -
<xliff:g id="time">%2$s</xliff:g> until full on AC</string>
+ <!-- [CHAR_LIMIT=40] Short label for battery level chart when charging with duration -->
+ <string name="power_charging_duration_ac_short"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g></string>
<!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
<string name="power_charging_duration_usb"><xliff:g id="level">%1$s</xliff:g> -
<xliff:g id="time">%2$s</xliff:g> until full over USB</string>
+ <!-- [CHAR_LIMIT=40] Short label for battery level chart when charging with duration -->
+ <string name="power_charging_duration_usb_short"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g></string>
<!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
<string name="power_charging_duration_wireless"><xliff:g id="level">%1$s</xliff:g> -
<xliff:g id="time">%2$s</xliff:g> until full from wireless</string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
+ <string name="power_charging_duration_wireless_short"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g></string>
<!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="battery_info_status_unknown">Unknown</string>
@@ -759,10 +778,16 @@
<string name="battery_info_status_charging">Charging</string>
<!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging on AC. -->
<string name="battery_info_status_charging_ac">Charging on AC</string>
+ <!-- [CHAR_LIMIT=20] Battery short status label when charing on AC -->
+ <string name="battery_info_status_charging_ac_short">Charging</string>
<!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging over USB. -->
<string name="battery_info_status_charging_usb">Charging over USB</string>
+ <!-- [CHAR_LIMIT=20] Battery short status label when charging over USB. -->
+ <string name="battery_info_status_charging_usb_short">Charging</string>
<!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging over a wireless connection. -->
<string name="battery_info_status_charging_wireless">Charging wirelessly</string>
+ <!-- [CHAR_LIMIT=20] Battery short status label when charging wirelessly. -->
+ <string name="battery_info_status_charging_wireless_short">Charging</string>
<!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="battery_info_status_discharging">Not charging</string>
<!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
index 6b29e2165c54..fa1f91fe9fbc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
@@ -25,6 +25,7 @@ import android.os.BatteryStats.HistoryItem;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.format.Formatter;
+import android.util.Log;
import android.util.SparseIntArray;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settingslib.graph.UsageView;
@@ -95,6 +96,11 @@ public class BatteryInfo {
}
public static void getBatteryInfo(final Context context, final Callback callback) {
+ BatteryInfo.getBatteryInfo(context, callback, false);
+ }
+
+ public static void getBatteryInfo(final Context context, final Callback callback,
+ boolean shortString) {
new AsyncTask<Void, Void, BatteryStats>() {
@Override
protected BatteryStats doInBackground(Void... params) {
@@ -109,14 +115,20 @@ public class BatteryInfo {
Intent batteryBroadcast = context.registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
BatteryInfo batteryInfo = BatteryInfo.getBatteryInfo(context,
- batteryBroadcast, batteryStats, elapsedRealtimeUs);
+ batteryBroadcast, batteryStats, elapsedRealtimeUs, shortString);
callback.onBatteryInfoLoaded(batteryInfo);
}
}.execute();
}
public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
- BatteryStats stats, long elapsedRealtimeUs) {
+ BatteryStats stats, long elapsedRealtimeUs) {
+ return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats, elapsedRealtimeUs,
+ false);
+ }
+
+ public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
+ BatteryStats stats, long elapsedRealtimeUs, boolean shortString) {
BatteryInfo info = new BatteryInfo();
info.mStats = stats;
info.mBatteryLevel = Utils.getBatteryLevel(batteryBroadcast);
@@ -129,9 +141,13 @@ public class BatteryInfo {
info.remainingTimeUs = drainTime;
String timeString = Formatter.formatShortElapsedTime(context,
drainTime / 1000);
- info.remainingLabel = resources.getString(R.string.power_remaining_duration_only,
+ info.remainingLabel = resources.getString(
+ shortString ? R.string.power_remaining_duration_only_short
+ : R.string.power_remaining_duration_only,
timeString);
- info.mChargeLabelString = resources.getString(R.string.power_discharging_duration,
+ info.mChargeLabelString = resources.getString(
+ shortString ? R.string.power_discharging_duration_short
+ : R.string.power_discharging_duration,
info.batteryPercentString, timeString);
} else {
info.remainingLabel = null;
@@ -140,7 +156,7 @@ public class BatteryInfo {
} else {
final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
final String statusLabel = Utils.getBatteryStatus(
- resources, batteryBroadcast);
+ resources, batteryBroadcast, shortString);
final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
@@ -151,13 +167,17 @@ public class BatteryInfo {
int plugType = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
int resId;
if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
- resId = R.string.power_charging_duration_ac;
+ resId = shortString ? R.string.power_charging_duration_ac_short
+ : R.string.power_charging_duration_ac;
} else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
- resId = R.string.power_charging_duration_usb;
+ resId = shortString ? R.string.power_charging_duration_usb_short
+ : R.string.power_charging_duration_usb;
} else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
- resId = R.string.power_charging_duration_wireless;
+ resId = shortString ? R.string.power_charging_duration_wireless_short
+ : R.string.power_charging_duration_wireless;
} else {
- resId = R.string.power_charging_duration;
+ resId = shortString ? R.string.power_charging_duration_short
+ : R.string.power_charging_duration;
}
info.remainingLabel = resources.getString(R.string.power_remaining_duration_only,
timeString);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index e86ca82bf215..59637bee2e87 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -459,58 +459,40 @@ public class RestrictedLockUtils {
LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
EnforcedAdmin enforcedAdmin = null;
final int userId = UserHandle.myUserId();
- if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
- // userId is managed profile and has a separate challenge, only consider
- // the admins in that user.
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
+ final UserManager um = UserManager.get(context);
+ final List<UserInfo> profiles = um.getProfiles(userId);
+ final int profilesSize = profiles.size();
+ // As we do not have a separate screen lock timeout settings for work challenge,
+ // we need to combine all profiles maximum time to lock even work challenge is
+ // enabled.
+ for (int i = 0; i < profilesSize; i++) {
+ final UserInfo userInfo = profiles.get(i);
+ final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
if (admins == null) {
- return null;
+ continue;
}
for (ComponentName admin : admins) {
- if (dpm.getMaximumTimeToLock(admin, userId) > 0) {
+ if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userId);
+ enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
} else {
return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
- }
- }
- } else {
- // Return all admins for this user and the profiles that are visible from this
- // user that do not use a separate work challenge.
- final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
- for (UserInfo userInfo : um.getProfiles(userId)) {
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
- if (admins == null) {
+ // This same admins could have set policies both on the managed profile
+ // and on the parent. So, if the admin has set the policy on the
+ // managed profile here, we don't need to further check if that admin
+ // has set policy on the parent admin.
continue;
}
- final boolean isSeparateProfileChallengeEnabled =
- lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
- for (ComponentName admin : admins) {
- if (!isSeparateProfileChallengeEnabled) {
- if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
- // This same admins could have set policies both on the managed profile
- // and on the parent. So, if the admin has set the policy on the
- // managed profile here, we don't need to further check if that admin
- // has set policy on the parent admin.
- continue;
- }
- }
- if (userInfo.isManagedProfile()) {
- // If userInfo.id is a managed profile, we also need to look at
- // the policies set on the parent.
- DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
- if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
+ if (userInfo.isManagedProfile()) {
+ // If userInfo.id is a managed profile, we also need to look at
+ // the policies set on the parent.
+ final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+ if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
+ if (enforcedAdmin == null) {
+ enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+ } else {
+ return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 74c1ebdd2a79..586f2690ba1f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -112,20 +112,26 @@ public class Utils {
}
public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) {
- final Intent intent = batteryChangedIntent;
+ return Utils.getBatteryStatus(res, batteryChangedIntent, false);
+ }
- int plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
- int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+ public static String getBatteryStatus(Resources res, Intent batteryChangedIntent,
+ boolean shortString) {
+ int plugType = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+ int status = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
String statusString;
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
int resId;
if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
- resId = R.string.battery_info_status_charging_ac;
+ resId = shortString ? R.string.battery_info_status_charging_ac_short
+ : R.string.battery_info_status_charging_ac;
} else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
- resId = R.string.battery_info_status_charging_usb;
+ resId = shortString ? R.string.battery_info_status_charging_usb_short
+ : R.string.battery_info_status_charging_usb;
} else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
- resId = R.string.battery_info_status_charging_wireless;
+ resId = shortString ? R.string.battery_info_status_charging_wireless_short
+ : R.string.battery_info_status_charging_wireless;
} else {
resId = R.string.battery_info_status_charging;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index aa95be27ea52..d7c9eab6074b 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -144,7 +144,9 @@ final class PbapClientProfile implements LocalBluetoothProfile {
return true;
}
}
- mService.disconnect(device);
+ for (BluetoothDevice src : srcs) {
+ mService.disconnect(device);
+ }
}
Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index c131fa5d547c..7ca76141a84c 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -463,7 +463,6 @@ public class BugreportProgressService extends Service {
.setContentTitle(title)
.setTicker(title)
.setContentText(name)
- .setContentInfo(percentageText)
.setProgress(info.max, info.progress, false)
.setOngoing(true)
.setContentIntent(infoPendingIntent)
@@ -958,7 +957,7 @@ public class BugreportProgressService extends Service {
.setDeleteIntent(newCancelIntent(context, info));
if (!TextUtils.isEmpty(info.name)) {
- builder.setContentInfo(info.name);
+ builder.setSubText(info.name);
}
Log.v(TAG, "Sending 'Share' notification for ID " + info.id + ": " + title);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 983944628bd9..9e2442cc2357 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -184,6 +184,14 @@
android:exported="true"
/>
+ <!-- Recents depends on every user having their own SystemUI process, so on user switch,
+ ensure that the process is created by starting this service.
+ -->
+ <service android:name="SystemUISecondaryUserService"
+ android:exported="true"
+ android:permission="com.android.systemui.permission.SELF" />
+
+
<!-- started from PhoneWindowManager
TODO: Should have an android:permission attribute -->
<service android:name=".screenshot.TakeScreenshotService"
@@ -366,7 +374,6 @@
android:name="com.android.systemui.tv.pip.PipOverlayActivity"
android:exported="true"
android:theme="@style/PipTheme"
- android:launchMode="singleTop"
android:taskAffinity=""
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:resizeableActivity="true"
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml
new file mode 100644
index 000000000000..6519673de871
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:pathData="M0 0h24v24H0z" />
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M22 3H7c-.69 0-1.23 .35 -1.59 .88 L0 12l5.41 8.11c.36 .53 .9 .89
+1.59 .89 h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59
+12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_down.xml b/packages/SystemUI/res/drawable/ic_ksh_key_down.xml
new file mode 100644
index 000000000000..25a2560c938b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_down.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
+ <path android:pathData="M0-.75h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml b/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml
new file mode 100644
index 000000000000..599f35001293
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:pathData="M0 0h24v24H0z" />
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_left.xml b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml
new file mode 100644
index 000000000000..038187e86acb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml
new file mode 100644
index 000000000000..1e2195edaf21
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91
+3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27 .28 v.79l5 4.99L20.49
+19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5
+14z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_right.xml b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml
new file mode 100644
index 000000000000..f2d73150705a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_up.xml b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml
new file mode 100644
index 000000000000..36a83b1d1e82
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_close_button.xml b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
index 86fda0d31346..186a4bae8942 100644
--- a/packages/SystemUI/res/drawable/tv_pip_close_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
@@ -19,8 +19,20 @@
<item android:state_focused="true">
<layer-list>
<item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_close_white" />
+ <item android:drawable="@drawable/ic_close_white"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
+ </layer-list>
+ </item>
+ <item>
+ <layer-list>
+ <item android:drawable="@drawable/ic_close_white"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
</layer-list>
</item>
- <item android:drawable="@drawable/ic_close_white" />
</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_full_button.xml b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
index 332c669de154..c48dc8287546 100644
--- a/packages/SystemUI/res/drawable/tv_pip_full_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
@@ -19,8 +19,20 @@
<item android:state_focused="true">
<layer-list>
<item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_fullscreen_white_24dp" />
+ <item android:drawable="@drawable/ic_fullscreen_white_24dp"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
+ </layer-list>
+ </item>
+ <item>
+ <layer-list>
+ <item android:drawable="@drawable/ic_fullscreen_white_24dp"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
</layer-list>
</item>
- <item android:drawable="@drawable/ic_fullscreen_white_24dp" />
</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
index d277b07c199e..bcc89739474a 100644
--- a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
@@ -19,8 +19,20 @@
<item android:state_focused="true">
<layer-list>
<item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_pause_white_24dp" />
+ <item android:drawable="@drawable/ic_pause_white_24dp"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
+ </layer-list>
+ </item>
+ <item>
+ <layer-list>
+ <item android:drawable="@drawable/ic_pause_white_24dp"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
</layer-list>
</item>
- <item android:drawable="@drawable/ic_pause_white_24dp" />
</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_play_button.xml b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
index fecdc095dac4..f77ea1df1c53 100644
--- a/packages/SystemUI/res/drawable/tv_pip_play_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
@@ -19,8 +19,20 @@
<item android:state_focused="true">
<layer-list>
<item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+ <item android:drawable="@drawable/ic_play_arrow_white_24dp"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
+ </layer-list>
+ </item>
+ <item>
+ <layer-list>
+ <item android:drawable="@drawable/ic_play_arrow_white_24dp"
+ android:top="@dimen/tv_pip_button_icon_padding"
+ android:bottom="@dimen/tv_pip_button_icon_padding"
+ android:left="@dimen/tv_pip_button_icon_padding"
+ android:right="@dimen/tv_pip_button_icon_padding" />
</layer-list>
</item>
- <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
</selector>
diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
index af3e3796d157..8e7feec94062 100644
--- a/packages/SystemUI/res/layout/battery_detail.xml
+++ b/packages/SystemUI/res/layout/battery_detail.xml
@@ -26,10 +26,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="72dp"
- android:paddingBottom="@dimen/battery_detail_graph_space_top"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/colorAccent" />
+ <com.android.systemui.ResizingSpace
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/battery_detail_graph_space_top" />
+
<com.android.settingslib.graph.UsageView
android:id="@+id/battery_usage"
android:layout_width="match_parent"
@@ -40,11 +43,14 @@
android:colorAccent="?android:attr/colorAccent"
systemui:textColor="#66FFFFFF" />
+ <com.android.systemui.ResizingSpace
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/battery_detail_graph_space_bottom" />
+
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
- android:layout_marginTop="@dimen/battery_detail_graph_space_bottom"
android:layout_marginBottom="8dp" />
<RelativeLayout
diff --git a/packages/SystemUI/res/values-h560dp/config.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
index 8b576b924632..0cecb96fd022 100644
--- a/packages/SystemUI/res/values-h560dp/config.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2014 The Android Open Source Project
+ ~ Copyright (C) 2016 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -15,9 +15,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<resources>
- <!-- The maximum number of items to be displayed in quick settings -->
- <integer name="quick_settings_detail_max_item_count">6</integer>
-</resources>
-
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/ksh_item_padding"
+ android:layout_marginStart="@dimen/ksh_item_margin_start"
+ android:scaleType="fitXY"
+ android:background="@color/ksh_key_item_background"/>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
index 5002c1298eb2..1215029bdda0 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -17,9 +17,9 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="4dp"
- android:padding="4dp"
- android:background="#EEEEEE"
- android:textColor="#8C000000"
+ android:padding="@dimen/ksh_item_padding"
+ android:layout_marginStart="@dimen/ksh_item_margin_start"
+ android:background="@color/ksh_key_item_background"
+ android:textColor="@color/ksh_key_item_color"
android:singleLine="true"
- android:textSize="14sp"/>
+ android:textSize="@dimen/ksh_item_text_size"/>
diff --git a/core/res/res/layout/notification_action_list.xml b/packages/SystemUI/res/layout/qs_customize_tile_divider.xml
index 400decc49945..0d932acb2c50 100644
--- a/core/res/res/layout/notification_action_list.xml
+++ b/packages/SystemUI/res/layout/qs_customize_tile_divider.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!--
+ Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,17 +15,11 @@
limitations under the License.
-->
-<LinearLayout
+<View
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/actions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:visibility="gone"
- android:layout_marginBottom="8dp"
- android:showDividers="middle"
- android:divider="?android:attr/listDivider"
- android:dividerPadding="12dp"
- >
- <!-- actions will be added here -->
-</LinearLayout>
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:background="?android:attr/listDivider"
+ android:importantForAccessibility="no" />
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 3358a1869bdf..af2a28521c99 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -25,13 +25,15 @@
android:visibility="invisible"
android:orientation="vertical">
+ <com.android.systemui.ResizingSpace
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_detail_margin_top" />
+
<include
android:id="@+id/qs_detail_header"
layout="@layout/qs_detail_header"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="28dp"
- />
+ android:layout_height="wrap_content" />
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/qs_detail_header_progress"
diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml
index c22e42c2e28f..f1a8d63d13dc 100644
--- a/packages/SystemUI/res/layout/qs_detail_items.xml
+++ b/packages/SystemUI/res/layout/qs_detail_items.xml
@@ -16,17 +16,19 @@
-->
<!-- extends FrameLayout -->
<com.android.systemui.qs.QSDetailItems xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="16dp"
+ android:paddingTop="@dimen/qs_detail_items_padding_top"
android:paddingStart="16dp"
android:paddingEnd="16dp">
- <LinearLayout
+ <com.android.systemui.qs.AutoSizingList
android:id="@android:id/list"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ sysui:itemHeight="@dimen/qs_detail_item_height" />
<LinearLayout
android:id="@android:id/empty"
@@ -48,9 +50,4 @@
android:layout_marginTop="20dp"
android:textAppearance="@style/TextAppearance.QS.DetailEmpty" />
</LinearLayout>
-
- <View
- android:id="@+id/min_height_spacer"
- android:layout_width="match_parent"
- android:layout_height="0dp"/>
-</com.android.systemui.qs.QSDetailItems> \ No newline at end of file
+</com.android.systemui.qs.QSDetailItems>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
index 224a0a0fd859..60112be21175 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
@@ -112,21 +112,6 @@
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:scaleType="matrix"
- android:src="@drawable/screen_pinning_light_bg_circ" />
-
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
- android:paddingStart="@dimen/screen_pinning_request_inner_padding"
- android:paddingTop="@dimen/screen_pinning_request_inner_padding"
- android:scaleType="matrix"
- android:src="@drawable/screen_pinning_bg_circ" />
-
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
index 1e5193ff9925..ebad7a4085be 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
@@ -43,21 +43,6 @@
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:scaleType="matrix"
- android:src="@drawable/screen_pinning_light_bg_circ" />
-
- <ImageView
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:scaleType="matrix"
- android:paddingLeft="@dimen/screen_pinning_request_inner_padding"
- android:paddingTop="@dimen/screen_pinning_request_inner_padding"
- android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
- android:src="@drawable/screen_pinning_bg_circ" />
-
- <ImageView
- android:layout_height="match_parent"
- android:layout_width="match_parent"
android:scaleType="center"
android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 47d3bffd6a63..3fa6245b7bde 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Maak <xliff:g id="APP">%s</xliff:g> toe."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwerp."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle onlangse programme is toegemaak."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Begin tans <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Kennisgewing is toegemaak."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Tuis"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Onlangs"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Terug"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Kennisgewings"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Kortpadsleutels"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Wissel invoermetode"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Programme"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Bystand"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Blaaier"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakte"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pos"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Kitsboodskappe"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiek"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Wys saam met volumekontroles"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Moenie steur nie"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Volumeknoppieskortpad"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f2afb8f563e9..eb5d256bf079 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> አስወግድ።"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ተሰናብቷል::"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ሁሉም የቅርብ ጊዜ ማመልከቻዎች ተሰናብተዋል።"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> በመጀመር ላይ።"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ማሳወቂያ ተወግዷል።"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"መነሻ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"የቅርብ ጊዜዎቹ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ተመለስ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ማሳወቂያዎች"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"የቁልፍ ሰሌዳ አቋራጮች"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"የግቤት ስልት ቀይር"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"መተግበሪያዎች"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ረዳት"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"አሳሽ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"እውቂያዎች"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ኢሜይል"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"ፈጣን መልዕክት"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ሙዚቃ"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"የቀን መቁጠሪያ"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"ከድምፅ መቆጣጠሪያዎች ጋር አሳይ"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"አትረብሽ"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"የድምፅ አዝራሮች አቋራጭ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f949eaf5f0bf..82a772c0e028 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -172,6 +172,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"إزالة <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"تمت إزالة <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"تم تجاهل كل التطبيقات المستخدمة مؤخرًا."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"جارٍ بدء <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"تم تجاهل الإشعار."</string>
@@ -532,6 +534,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"الشاشة الرئيسية"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"الأحدث"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"رجوع"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"الإشعارات"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"اختصارات لوحة المفاتيح"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"تبديل أسلوب الإدخال"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"التطبيقات"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"التطبيق المساعد"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"المتصفح"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"جهات الاتصال"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"البريد الإلكتروني"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"الرسائل الفورية"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"الموسيقى"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"التقويم"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"عرض مع عناصر التحكم في مستوى الصوت"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"الرجاء عدم الإزعاج"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"اختصار أزرار مستوى الصوت"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 3aa911ffad71..59b31419ac17 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> kənarlaşdırın."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> çıxarıldı."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Bütün son tətbiqlər kənarlaşdırıldı."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlanır."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildiriş uzaqlaşdırıldı."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Əsas səhifə"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Sonuncular"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Geri"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Bildirişlər"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klaviatura qısa yolları"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Daxiletmə metoduna keçin"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Tətbiqlər"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Yardım"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauzer"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktlar"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-poçt"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiqi"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Təqvim"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Həcm nəzarəti ilə göstərin"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Narahat etməyin"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Səs düymələri qısayolu"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index cc091f646381..0945885077ed 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -169,6 +169,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacite <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je odbačena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korišćene aplikacije su odbačene."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokrećemo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obaveštenje je odbačeno."</string>
@@ -529,6 +531,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početni"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni sadržaj"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obaveštenja"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tasterske prečice"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promeni metod unosa"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Aplikacija za pomoć"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Pregledač"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Imejl"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Razmena trenutnih poruka"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži sa kontrolama jačine zvuka"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne uznemiravaj"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Prečica za dugmad za jačinu zvuka"</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index a496330b6bf1..726a0e77073e 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -172,6 +172,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Выдаліць <xliff:g id="APP">%s</xliff:g> са спіса апошніх."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> выдалены."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усе апошнія праграмы адхілены."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запускаецца <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Апавяшчэнне прапушчана."</string>
@@ -532,6 +534,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Галоўная"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Апошнія"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Апавяшчэнні"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Спалучэнні клавіш для хуткага доступу"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Пераключэнне рэжыму ўводу"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Праграмы"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Памочнік"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браўзер"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Кантакты"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электронная пошта"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Iмгненныя паведамленнi"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Каляндар"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Паказаць з рэгулятарамі гучнасці"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не турбаваць"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Доступ праз кнопкі рэгулявання гучнасці"</string>
@@ -588,12 +602,12 @@
<string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Перамясціць управа"</string>
<string name="forced_resizable_info_text" msgid="7591061837558867999">"Праграма можа не працаваць у рэжыме некалькіх вокнаў"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Краніце двойчы, каб рэдагаваць."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>, краніце двойчы, каб дадаць."</string>
+ <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Краніце двойчы, каб дадаць."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>. Краніце двойчы, каб выбраць."</string>
<string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Перамясціць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Выдаліць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> дададзена ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> выдалена"</string>
+ <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Плітка <xliff:g id="TILE_NAME">%1$s</xliff:g> дададзена ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Плітка <xliff:g id="TILE_NAME">%1$s</xliff:g> выдалена"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> перамешчана ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Рэдактар хуткіх налад."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 1479beaa8706..479087ac9c87 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отхвърляне на <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложението <xliff:g id="APP">%s</xliff:g> е отхвърлено."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Всички скорошни приложения са отхвърлени."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> се стартира."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известието е отхвърлено."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Начало"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Скорошни"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Известия"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Клавишни комбинации"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Превключване на метода на въвеждане"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Приложения"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помощно приложение"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузър"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Електронна поща"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Незабавни съобщения"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Показване с контролите за силата на звука"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не безпокойте"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Пряк път към бутоните за силата на звука"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index ed8b06678bcb..ccbcb6ec1647 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> খারিজ করুন।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> খারিজ করা হয়েছে৷"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"সমস্ত সাম্প্রতিক অ্যাপ্লিকেশন খারিজ করা হয়েছে।"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> তারাঙ্কিত করা হচ্ছে।"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"বিজ্ঞপ্তি খারিজ করা হয়েছে৷"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"হোম"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"সাম্প্রতিকগুলি"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"পিছনে"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"বিজ্ঞপ্তিগুলি"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"কীবোর্ড শর্টকাট"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ইনপুট পদ্ধতি পাল্টান"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"অ্যাপ্লিকেশানগুলি"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"সহযোগিতা"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ব্রাউজার"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"পরিচিতি"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ইমেল"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"সংগীত"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ক্যালেন্ডার"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"ভলিউম নিয়ন্ত্রণ সহ দেখান"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"বিরক্ত করবেন না"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ভলিউম বোতামের শর্টকাট"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index c6201786c00f..c5398a2cb6e2 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -169,6 +169,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbaci aplikaciju <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> uklonjena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korištene aplikacije su odbačene."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokrećem aplikaciju <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavještenje je uklonjeno."</string>
@@ -529,6 +531,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početak"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni ekrani"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obavještenja"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Skracenice tastature"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promijeni način unosa"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoć"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikazati sa kontrolama jačine zvuka"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne ometaj"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Prečica za dugmad za Jačinu zvuka"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0145c2a93b37..b7fffb7fda52 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignora <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"S\'han descartat totes les aplicacions recents."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"S\'està iniciant <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inici"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recents"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Enrere"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificacions"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tecles de drecera"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Canvia el mètode d\'introducció"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicacions"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistència"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactes"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correu electrònic"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendari"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostra amb els controls de volum"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No molesteu"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Drecera per als botons de volum"</string>
@@ -583,13 +597,13 @@
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mou a l\'esquerra"</string>
<string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mou a la dreta"</string>
<string name="forced_resizable_info_text" msgid="7591061837558867999">"És possible que l\'aplicació no funcioni amb el Mode multifinestra"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, mosaic <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-lo."</string>
+ <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string>
+ <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-ho."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posició <xliff:g id="POSITION">%1$d</xliff:g>. Fes doble toc per seleccionar-la."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mou el mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Suprimeix el mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"El mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha afegit a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"El mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha suprimit"</string>
- <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"El mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha mogut a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
+ <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Suprimeix <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha afegit a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha suprimit"</string>
+ <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha mogut a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de la configuració ràpida."</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ec2011f9882b..b707ece9e9eb 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zavřít aplikaci <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikace <xliff:g id="APP">%s</xliff:g> byla odebrána."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všechny naposledy použité aplikace byly odstraněny."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spouštění aplikace <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Oznámení je zavřeno."</string>
@@ -530,6 +532,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Plocha"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Poslední"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Zpět"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Oznámení"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klávesové zkratky"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Přepnout metodu zadávání"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikace"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistence"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Prohlížeč"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Hudba"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendář"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Zobrazit včetně ovládacích prvků hlasitosti"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nerušit"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Zkratka tlačítek hlasitosti"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 87111003ddd0..7a25141257aa 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Afvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> er annulleret."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle de seneste applikationer er lukket."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> startes."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Underretningen er annulleret."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Start"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Seneste"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tilbage"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Underretninger"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tastaturgenveje"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Skift indtastningsmetode"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applikationer"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktpersoner"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Vis med lydstyrkeregulering"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Forstyr ikke"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Genvej til lydstyrkeknapper"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 2daa00f085d3..e10eb649af41 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> beenden"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> entfernt"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle kürzlich verwendeten Apps wurden entfernt."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> wird gestartet."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Benachrichtigung geschlossen"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startseite"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Letzte"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Zurück"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Benachrichtigungen"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tastenkombinationen"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Eingabemethode wechseln"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Apps"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistent"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakte"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-Mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Einschließlich Lautstärkeregler anzeigen"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Bitte nicht stören"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Tastenkombination für Lautstärketasten"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 34385f335307..5ec313398fb3 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Παράβλεψη <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Απορρίφθηκαν <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Έγινε παράβλεψη όλων των πρόσφατων εφαρμογών."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Έναρξη <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Η ειδοποίηση έχει απορριφθεί."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Αρχική οθόνη"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Πρόσφατα"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Πίσω"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Ειδοποιήσεις"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Συντομεύσεις πληκτρολογίου"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Εναλλαγή μεθόδου εισαγωγής"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Εφαρμογές"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Υποβοήθηση"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Πρόγραμμα περιήγησης"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Επαφές"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Ηλεκτρονικό ταχυδρομείο"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Άμεσα μηνύματα (ΙΜ)"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Μουσική"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Ημερολόγιο"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Εμφάνιση με στοιχεία ελέγχου έντασης ήχου"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Μην ενοχλείτε"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Συντόμευση κουμπιών έντασης ήχου"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 71a8ad783893..f08894fb39b8 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Keyboard Shortcuts"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Switch input method"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 71a8ad783893..f08894fb39b8 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Keyboard Shortcuts"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Switch input method"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 71a8ad783893..f08894fb39b8 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Keyboard Shortcuts"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Switch input method"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 35d0f470fc7d..b5a10e1f5e4d 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rechazar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartada."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se descartaron todas las aplicaciones recientes."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Pantalla principal"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificaciones"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Combinación de teclas"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar método de entrada"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicaciones"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistencia"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar con controles de volumen"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No interrumpir"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Combinación de teclas de botones de volumen"</string>
@@ -582,7 +596,7 @@
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover hacia arriba"</string>
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover a la izquierda"</string>
<string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover a la derecha"</string>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Es posible que la app no funcione con la función Multiventana"</string>
+ <string name="forced_resizable_info_text" msgid="7591061837558867999">"Es posible que la app no se ejecute con la función Multiventana"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Presiona dos veces para editarla."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Presiona dos veces para agregarlo."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Presiona dos veces para seleccionarla."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a976a9c40a53..d8affc9f81dd 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Se ha eliminado <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se han ignorado todas las aplicaciones recientes."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inicio"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificaciones"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Combinaciones de teclas"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar método de introducción"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicaciones"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistencia"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar con controles de volumen"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No molestar"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Combinación de teclas para los botones de volumen"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index e7bfdffe94d1..f18bf05f1599 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rakendusest <xliff:g id="APP">%s</xliff:g> loobumine."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Loobusite rakendusest <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kõikidest hiljutistest rakendustest on loobutud"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Rakenduse <xliff:g id="APP">%s</xliff:g> käivitamine."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g>, <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Märguandest on loobutud."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Avaekraan"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Hiljutised"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tagasi"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Märguanded"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klaviatuuri otseteed"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Sisestusmeetodi vahetamine"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Rakendused"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Abi"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktid"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM (kiirsuhtlus)"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muusika"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Kuva koos helitugevuse juhtnuppudega"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Mitte segada"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Helitugevuse nuppude otsetee"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index b9cb78e02914..575f87496e97 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Baztertu <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> baztertu da."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazio guztiak baztertu da."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> hasten."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Jakinarazpena baztertu da."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Hasierako pantaila"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Azkenak"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atzera"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Jakinarazpenak"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Lasterbideak"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Aldatu idazketa-metodoa"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikazioak"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Laguntzailea"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Arakatzailea"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktuak"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Helbide elektronikoa"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Istanteko mezularitza"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musika"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Egutegia"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Erakutsi bolumena kontrolatzeko aukerekin"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ez molestatu"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Bolumen-botoietarako lasterbidea"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index af744351445b..322197e1c990 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"رد کردن <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> نادیده گرفته شد."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"همه برنامه‌های اخیر رد شدند."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> در حال شروع به کار است."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"اعلان ردشد."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"صفحه اصلی"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"موارد اخیر"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"برگشت"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"اعلان‌ها"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"میان‌برهای صفحه‌کلید"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"تغییر روش ورودی"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"برنامه‌ها"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"دستیار"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"مرورگر"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"مخاطبین"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"رایانامه"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"پیام فوری"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"موسیقی"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"تقویم"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"نمایش با کنترل‌های صدا"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"مزاحم نشوید"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"میان‌بر دکمه‌های صدا"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 3b28199dc180..6db0a3e37848 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hylätään <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> hylättiin."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kaikki viimeisimmät sovellukset on hylätty."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Käynnistetään <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Aloitusnäyttö"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Viimeaikaiset"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Takaisin"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Ilmoitukset"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Pikanäppäimet"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Vaihda syöttötapaa"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Sovellukset"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Apusovellus"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Selain"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Yhteystiedot"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Sähköposti"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Pikaviesti"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiikki"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalenteri"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Näytä äänenvoimakkuuden säätimien yhteydessä"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Älä häiritse"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Äänenvoimakkuuspainikkeiden pikanäppäin"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 2ef24db03921..89c682634d25 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Accueil"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Récents"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Précédent"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Raccourcis clavier"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Changer de méthode d\'entrée"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navigateur"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Courriel"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musique"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Afficher avec les commandes de volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne pas déranger"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Raccourci des boutons de volume"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 93d9e14a9e6f..2f99b946a7aa 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> : <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Accueil"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Récents"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Précédent"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Raccourcis clavier"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Changer le mode de saisie"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navigateur"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Messagerie"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Messagerie instantanée"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musique"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Afficher avec les commandes de volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne pas déranger"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Raccourci des boutons de volume"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 86a0bfa44ea5..45c3626b0c6e 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rexeitar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Rexeitouse <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Rexeitáronse todas as aplicacións recentes."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación rexeitada"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inicio"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Volver"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificacións"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atallos de teclado"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar de método de entrada"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicacións"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistente"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar cos controis de volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Non molestar"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Atallo dos botóns de volume"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index d52226df4b8c..ef6a49c1043e 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખો."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખી."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"તમામ તાજેતરની એપ્લિકેશનો કાઢી નાખી."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> પ્રારંભ કરી રહ્યું છે."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"સૂચના કાઢી નાખી."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"હોમ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"તાજેતરના"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"પાછળ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"સૂચનાઓ"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"કીબોર્ડ શૉર્ટકટ્સ"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ઇનપુટ પદ્ધતિ સ્વિચ કરો"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ઍપ્લિકેશનો"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"સહાય"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"બ્રાઉઝર"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"સંપર્કો"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ઇમેઇલ"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"સંગીત"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"કૅલેન્ડર"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"વૉલ્યૂમ નિયંત્રણ સાથે બતાવો"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ખલેલ પાડશો નહીં"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"વૉલ્યૂમ બટન્સ શૉર્ટકટ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 160d4a09a203..1ba0cafe9806 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> को ख़ारिज करें."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"हाल ही के सभी ऐप्लिकेशन ख़ारिज कर दिए गए."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफिकेशन खारिज की गई."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"होम"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"हाल ही के"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"वापस जाएं"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"नोटिफ़िकेशन"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"कीबोर्ड शॉर्टकट"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट पद्धति‍ बदलें"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ऐप्लिकेशन"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहायक"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउज़र"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ईमेल"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"कैलेंडर"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"वॉल्यूम नियंत्रणों के साथ दिखाएं"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"परेशान न करें"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"वॉल्यूम बटन का शॉर्टकट"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index ddfcb553b180..81c627600613 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -169,6 +169,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacivanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> odbačena je."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Odbačene su sve nedavne aplikacije."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavijest je odbačena."</string>
@@ -529,6 +531,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početni zaslon"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Najnovije"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Natrag"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obavijesti"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tipkovni prečaci"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promjena načina unosa"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoć"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Izravna poruka"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Glazba"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži s kontrolama glasnoće"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne uznemiravaj"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Prečac tipki za glasnoću"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index c026926ebb24..b7ac8a4ed1ba 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"A(z) <xliff:g id="APP">%s</xliff:g> elvetése."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eltávolítva."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Az összes alkalmazás eltávolítva a nemrég használtak közül."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A(z) <xliff:g id="APP">%s</xliff:g> indítása."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Értesítés elvetve."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Otthon"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Legutóbbiak"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Vissza"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Értesítések"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Billentyűkódok"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Beviteli mód váltása"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Alkalmazások"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Segédalkalmazás"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Böngésző"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Névjegyek"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Azonnali üzenetküldés"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Zene"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Naptár"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Megjelenítés hangerőszabályzóval"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne zavarjanak"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"A hangerőgombok gyorsbillentyűk"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index a9d122a0c899..7e4e01a4ccf9 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Անտեսել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>-ը անտեսված է:"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Բոլոր վերջին հավելվածները հեռացվել են ցուցակից:"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Մեկնարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Գլխավոր էջ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Վերջինները"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Հետ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Ծանուցումներ"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Ստեղնային դյուրանցումներ"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Փոխարկել մուտքագրման եղանակը"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Գործադիրներ"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Օգնություն"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Դիտարկիչ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Կոնտակտներ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Էլփոստ"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Երաժշտություն"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Օրացույց"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Ցույց տալ ձայնի ուժգնության կառավարման տարրերի հետ"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Չընդհատել"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Ձայնի կոճակների դյուրանցում"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 876034ce90b5..2b5142636535 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Menyingkirkan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru telah ditutup."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulai <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifikasi disingkirkan."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Layar Utama"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Terbaru"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Kembali"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifikasi"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Pintasan Keyboard"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Beralih metode masukan"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikasi"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Bantuan"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontak"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Tampilkan dengan kontrol volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Jangan ganggu"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Pintasan tombol volume"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 4ce5f548e25e..1dc37df36651 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hunsa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> vísað frá."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Öll nýleg forrit fjarlægð."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Ræsir <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Tilkynningu lokað."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Heim"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nýlegt"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Til baka"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Tilkynningar"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Flýtilyklar"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Skipta um innsláttaraðferð"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Forrit"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Aðstoð"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Vafri"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Tengiliðir"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Tölvupóstur"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Spjall"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Tónlist"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Dagatal"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Sýna með hljóðstyrksstillingum"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ónáðið ekki"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Flýtihnappar fyrir hljóðstyrk"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 62c18f2fc0d0..4a8ba9931f2f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Elimina <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eliminata."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tutte le applicazioni recenti sono state rimosse."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Avvio di <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifica eliminata."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recenti"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Indietro"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifiche"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Scorciatoie da tastiera"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambia metodo di immissione"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applicazioni"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistenza"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatti"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musica"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostra con controlli volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Non disturbare"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Pulsanti del volume come scorciatoia"</string>
@@ -585,7 +599,7 @@
<string name="forced_resizable_info_text" msgid="7591061837558867999">"L\'app potrebbe non funzionare con la modalità multi-finestra"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tocca due volte per modificare."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tocca due volte per aggiungere."</string>
- <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Positione <xliff:g id="POSITION">%1$d</xliff:g>. Tocca due volte per selezionare."</string>
+ <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>. Tocca due volte per selezionare."</string>
<string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Sposta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Rimuovi <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> è stato aggiunto alla posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 097b427cdd97..d41d50d399f4 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"סגור את <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> נדחה."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"כל האפליקציות האחרונות נסגרו."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"מפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"הודעה נדחתה."</string>
@@ -530,6 +532,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"דף הבית"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"אחרונים"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"הקודם"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"הודעות"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"מקשי קיצור במקלדת"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"החלפת שיטת קלט"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"אפליקציות"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"מסייע"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"דפדפן"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"אנשי קשר"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"אימייל"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"שליחת הודעות מיידיות"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"מוזיקה"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"‏YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"יומן"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"הצג עם פקדי עוצמת הקול"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"נא לא להפריע"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"מקש קיצור ללחצני עוצמת קול"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 61ff6d42ca3b..83a9888f2231 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>を削除します。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>は削除されました。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近のアプリケーションをすべて消去しました。"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>を開始しています。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知が削除されました。"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ホーム"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"戻る"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"キーボード ショートカット"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"入力方法の切り替え"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"アプリ"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"アシスト"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ブラウザ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"連絡先"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"メール"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音楽"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"カレンダー"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"音量調節を表示"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"通知の非表示"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"音量ボタンのショートカット"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 26f25293ca13..5008fe05e998 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-ის უგულებელყოფა."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ამოშლილია სიიდან."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ყველა ბოლო აპლიკაცია გაუქმდა."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> იწყება."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"შეტყობინება წაიშალა."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"მთავარი"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ბოლოს გამოყენებული"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"უკან"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"შეტყობინებები"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"კლავიატურის მალსახმობები"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"შეყვანის მეთოდის გადართვა"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"აპლიკაციები"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"დახმარება"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ბრაუზერი"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"კონტაქტები"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ელფოსტა"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"მუსიკა"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"კალენდარი"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"ხმის მართვის საშუალებების ჩვენება"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"არ შემაწუხოთ"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ხმის ღილაკების მალსახმობი"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 737041e3a045..ff33f0504ddd 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> қолданбасынан бас тарту."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> алынып тасталған."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Барлық жақындағы қабылданбаған қолданбалар."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> іске қосылуда."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Хабар алынып тасталды."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Негізгі бет"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Жақындағылар"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Артқа"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Хабарландырулар"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Пернелер тіркесімдері"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Енгізу әдісін ауыстыру"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Қолданбалар"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Көмекші"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузер"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контактілер"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электрондық пошта"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Mузыка"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Күнтізбе"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Дыбыс деңгейін басқару элементтерімен бірге көрсету"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Мазаламау"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Дыбыс деңгейі түймелерінің төте жолы"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 1cec0b002647..b69f893f0fbb 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"បោះបង់ <xliff:g id="APP">%s</xliff:g> ។"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"កម្មវិធីថ្មីៗទាំងអស់ត្រូវបានបោះបង់។"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ។"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"បាន​បដិសេធ​ការ​ជូនដំណឹង"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ដើម"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ថ្មីៗ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ថយក្រោយ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ការជូនដំណឹង"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ផ្លូវកាត់ក្ដារចុច"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ប្ដូរវិធីសាស្ត្របញ្ចូល"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"កម្មវិធី"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ជំនួយ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"កម្មវិធីរុករក"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ទំនាក់ទំនង"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"អ៊ីមែល"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"តន្ត្រី"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ប្រតិទិន"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"បង្ហាញជាមួយការគ្រប់គ្រងកម្រិតសំឡេង"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"កុំ​រំខាន"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ផ្លូវកាត់ប៊ូតុងកម្រិតសំឡេង"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 2eb614163e88..1ce14dd58df6 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸು."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ಇತ್ತೀಚಿನ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ಅಧಿಸೂಚನೆ ವಜಾಗೊಂಡಿದೆ."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ಮುಖಪುಟ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ಇತ್ತೀಚಿನವುಗಳು"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ಹಿಂದೆ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ಇನ್‌ಪುಟ್‌‌ ವಿಧಾನ ಬದಲಿಸಿ"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ಸಹಾಯ ಮಾಡು"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ಬ್ರೌಸರ್"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ಸಂಪರ್ಕಗಳು"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ಇಮೇಲ್"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ಸಂಗೀತ"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ಕ್ಯಾಲೆಂಡರ್"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಣಗಳ ಜೊತೆಗೆ ತೋರಿಸು"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳ ಶಾರ್ಟ್‌ಕಟ್‌"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ae60d0eeaa85..a8a2a0a2758e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>을(를) 숨깁니다."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>이(가) 제거되었습니다."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"최근 사용한 애플리케이션을 모두 닫았습니다."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>을(를) 시작하는 중입니다."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"알림이 제거되었습니다."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"홈"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"최근"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"뒤로"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"알림"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"단축키"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"입력 방법 전환"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"애플리케이션"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"지원"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"브라우저"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"주소록"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"이메일"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"메신저"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"음악"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"캘린더"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"볼륨 컨트롤과 함께 표시"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"알림 일시중지"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"볼륨 버튼 단축키"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index b035bbb1d13f..6a2d77fe0a04 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> этибарга албоо."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> жок болду."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Акыркы колдонмолордун баары көз жаздымда калтырылды."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> иштеп баштоодо."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Эскертме жок кылынды."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Башкы бет"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Акыркылар"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Артка"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Эскертмелер"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Баскычтоптун кыска жолдору"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Киргизүү ыкмасын которуштуруу"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Колдонмолор"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Көмөкчү"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Серепчи"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Байланыштар"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электрондук почта"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Жылнаама"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Үн көзөмөлдөгүчтөрү менен көрсөтүлсүн"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Тынчымды алба"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Үндү көзөмөлдөөчү баскычтардын кыска жолдору"</string>
@@ -582,7 +596,7 @@
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Жогору жылдыруу"</string>
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Солго жылдыруу"</string>
<string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Оңго жылдыруу"</string>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Көп терезе режиминде колдонмо иштебей калышы мүмкүн"</string>
+ <string name="forced_resizable_info_text" msgid="7591061837558867999">"Бир нече терезе режиминде колдонмо иштебей калышы мүмкүн"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Түзөтүү үчүн эки жолу таптаңыз."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Кошуу үчүн эки жолу таптаңыз."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>. Тандоо үчүн эки жолу таптаңыз."</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 26a81c8d835c..c40797c6ebaa 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -24,4 +24,14 @@
<dimen name="docked_divider_handle_width">2dp</dimen>
<dimen name="docked_divider_handle_height">16dp</dimen>
+
+ <dimen name="qs_tile_margin_top">2dp</dimen>
+ <dimen name="qs_brightness_padding_top">0dp</dimen>
+
+ <dimen name="battery_detail_graph_space_top">9dp</dimen>
+ <dimen name="battery_detail_graph_space_bottom">9dp</dimen>
+
+ <integer name="quick_settings_num_columns">4</integer>
+ <bool name="quick_settings_wide">true</bool>
+ <dimen name="qs_detail_margin_top">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 2355a84d9cb3..601cc2a6c075 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ປິດ <xliff:g id="APP">%s</xliff:g> ໄວ້."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"ປິດ <xliff:g id="APP">%s</xliff:g> ແລ້ວ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ທຸກ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ບໍ່​ດົນ​ມາ​ນີ້​ຖືກ​ປ່ອຍ​ໄປ."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ກຳ​ລັງ​ເປີດ <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ປິດການແຈ້ງເຕືອນແລ້ວ."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"​ໜ້າຫຼັກ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ຫາ​ກໍ​ໃຊ້"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ກັບຄືນ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ການແຈ້ງເຕືອນ"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ປຸ່ມລັດແປ້ນພິມ"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ແອັບພລິເຄຊັນ"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ຕົວຊ່ວຍ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ໂປຣແກຣມທ່ອງເວັບ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ລາຍຊື່ຜູ້ຕິດຕໍ່"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ອີເມວ"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ດົນຕີ"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ປະຕິທິນ"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"ສະແດງສ່ວນຄວບຄຸມສຽງ"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ຫ້າມ​ລົບ​ກວນ"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ທາງລັດປຸ່ມສຽງ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 93c0b6941208..866abf3f6e2f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Atsisakyti <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Atsisakyta programos „<xliff:g id="APP">%s</xliff:g>“."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Atsisakyta visų naujausių programų."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Paleidžiama <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"„<xliff:g id="APP">%1$s</xliff:g>“ <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pranešimo atsisakyta."</string>
@@ -530,6 +532,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Pagrindinis ekranas"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Naujausios veiklos ekranas"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atgal"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Pranešimai"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Spartieji klavišai"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Perjungti įvesties metodą"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Programos"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pagalbinė programa"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Naršyklė"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktai"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"El. paštas"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"TP"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendorius"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Rodyti su garsumo valdikliais"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Netrukdymo režimas"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Garsumo mygtukų spartusis klavišas"</string>
@@ -590,7 +604,7 @@
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis. Dukart palieskite, kad pasirinktumėte."</string>
<string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
<string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Pašalinti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
- <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pridėtas prie <xliff:g id="POSITION">%2$d</xliff:g> pozicijos"</string>
+ <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pridėtas prie <xliff:g id="POSITION">%2$d</xliff:g> padėties"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pašalintas"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ perkeltas į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Sparčiųjų nustatymų redagavimo priemonė."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0ee306be07da..9c32b3190744 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -169,6 +169,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Nerādīt lietotni <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Lietotne <xliff:g id="APP">%s</xliff:g> vairs netiek rādīta."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Visas nesen izmantotās lietojumprogrammas tika noņemtas."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Notiek lietotnes <xliff:g id="APP">%s</xliff:g> palaišana."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Paziņojums netiek rādīts."</string>
@@ -529,6 +531,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Sākums"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Pēdējie"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atpakaļ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Paziņojumi"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Īsinājumtaustiņi"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Pārslēgt ievades metodi"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Lietojumprogrammas"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Palīgs"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Pārlūkprogramma"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktpersonas"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pasts"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Tūlītējā ziņojumapmaiņa"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Mūzika"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendārs"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Rādīt ar skaļuma vadīklām"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Netraucēt"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Skaļuma pogu saīsne"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index cfacc43dafa3..7f2fc15ada68 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отфрли <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> е отфрлена."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Сите неодамнешни апликации се отфрлени."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Се стартува <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известувањето е отфрлено."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Почетна страница"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Неодамнешни"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Известувања"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Кратенки на тастатурата"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Префрли метод за внесување"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Апликации"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помош"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Прелистувач"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Е-пошта"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Прикажи со контроли за јачина на звук"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не вознемирувај"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Кратенка за копчињата за јачина на звук"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index deca89887f58..dfe992c31e9f 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> നിരസിക്കുക."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> നിരസിച്ചു."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"അടുത്തിടെയുള്ള എല്ലാ അപ്ലിക്കേഷനും നിരസിച്ചു."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കുന്നു."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"അറിയിപ്പ് നിരസിച്ചു."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"വീട്"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"പുതിയവ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"മടങ്ങുക"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"അറിയിപ്പുകൾ"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"കീബോർഡ് കുറുക്കുവഴികൾ"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ടൈപ്പിംഗ് രീതി മാറുക"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"അപ്ലിക്കേഷനുകൾ"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"അസിസ്റ്റ്"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ബ്രൗസർ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"കോൺടാക്റ്റുകൾ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ഇമെയിൽ"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"സംഗീതം"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"കലണ്ടർ"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"വോളിയം നിയന്ത്രണങ്ങളോടൊപ്പം കാണിക്കുക"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ശല്യപ്പെടുത്തരുത്"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"വോളിയം ബട്ടൺ കുറുക്കുവഴി"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index b701e21af902..80cb8f278dd4 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -166,6 +166,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-г хаах."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> байхгүй."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Хамгийн сүүлийн бүх програмыг арилгасан байна."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж байна."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Мэдэгдэл хаагдсан."</string>
@@ -526,6 +528,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Нүүр хуудас"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Саяхны"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Буцах"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Мэдэгдэл"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Гарын товчлол"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Оролтын аргыг солих"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Апп"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Дэмжлэг"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Хөтөч"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Харилцагчид"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Имэйл"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Хөгжим"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Хуанли"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Түвшний хяналттай харуулах"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Бүү саад бол"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Түвшний товчлуурын товчлол"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 6c6e6340a832..76dfcd555300 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> डिसमिस करा."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> डिसमिस केला."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अनुप्रयोग डिसमिस झाले."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करीत आहे."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना डिसमिस केल्या."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"मुख्यपृष्ठ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"अलीकडील"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"परत"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"सूचना"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"कीबोर्ड शॉर्टकट"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट पद्धत स्विच करा"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"अनुप्रयोग"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहाय्य"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउझर"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ईमेल"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"कॅलेंडर"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"आवाज नियंत्रणांसह दर्शवा"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"व्यत्यय आणू नका"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"आवाजाच्या बटणांचा शार्टकट"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 335ff4c465e0..9401198ec56b 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ketepikan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ditolak."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaharu diketepikan."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulakan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Skrin Utama"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Terbaharu"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Kembali"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Pemberitahuan"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Pintasan Papan Kekunci"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Tukar kaedah input"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikasi"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Bantu"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Penyemak imbas"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kenalan"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mel"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzik"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Tunjukkan dengan kawalan kelantangan"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Jangan ganggu"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Pintasan butang kelantangan"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index d309991a7467..69647503a056 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ကို ပယ်လိုက်ရန်"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ထုတ်ထားသည်။"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"မကြာသေးမီက အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်ပြီးပါပြီ။"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ကို စတင်နေသည်။"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g><xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"အကြောင်းကြားချက်ကိုဖယ်ရှားပြီး"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ပင်မ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"မကြာသေးခင်က"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"နောက်သို့"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"အကြောင်းကြားချက်များ"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ကီးဘုတ် ဖြတ်လမ်းများ"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ထည့်သွင်းမှုနည်းလမ်းကို ပြောင်းလဲပါ"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"အက်ပ်များ"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"အထောက်အကူ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ဘရောင်ဇာ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"အဆက်အသွယ်များ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"အီးမေးလ်"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"အမြန်စာတိုစနစ်"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ပြက္ခဒိန်"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"အသံထိန်းချုပ်သည့်ခလုတ်များဖြင့် ပြပါ"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"မနှောက်ယှက်ပါနှင့်"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"အသံထိန်းချုပ်သည့်ခလုတ် ဖြတ်လမ်း"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 8a961fc02c57..eed5f36ae95c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Avvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> avvist."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle nylig brukte apper er avvist."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starter <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Varselet ble skjult."</string>
@@ -400,7 +402,7 @@
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheten forblir låst til du låser den opp manuelt"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Motta varsler raskere"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Se dem før du låser opp"</string>
- <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nei, takk"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nei takk"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Konfigurer"</string>
<string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="volume_zen_end_now" msgid="3179845345429841822">"Avslutt nå"</string>
@@ -409,7 +411,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skjermen er låst"</string>
<string name="screen_pinning_description" msgid="3577937698406151604">"På denne måten blir skjermen synlig frem til du låser den opp. Trykk og hold inne Tilbake for å låse opp."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Skjønner"</string>
- <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei, takk"</string>
+ <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei takk"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igjen neste gang du slår den på i innstillingene."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startside"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nylige"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tilbake"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Varsler"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Hurtigtaster"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Bytt inndatametode"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Apper"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Nettleser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musikk"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Vis med volumkontrollene"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ikke forstyrr"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Hurtigtast for volumknappene"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 7e91a5383791..836dc4bf8fa3 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> खारेज गर्नुहोस्।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"सबै हालका अनुप्रयोगहरू खारेज गरियो।"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>सुरु गर्दै।"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"गृह"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"हालैका"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"पछाडि"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"सूचनाहरू"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"किबोर्ड सर्टकटहरू"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट विधिलाई स्विच गर्नुहोस्"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"अनुप्रयोगहरू"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहायता"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउजर"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"सम्पर्कहरू"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"इमेल"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"पात्रो"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"भोल्युम नियन्त्रणसहित देखाउनुहोस्"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"बाधा नपुर्याउनुहोस्"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"भोल्युम बटनका सर्टकट"</string>
@@ -582,7 +596,7 @@
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"माथि सार्नुहोस्"</string>
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"बाँया सार्नुहोस्"</string>
<string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"दायाँ सार्नुहोस्"</string>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"अनुप्रयोगले बहु-विन्डोमा काम नगर्न सक्छ"</string>
+ <string name="forced_resizable_info_text" msgid="7591061837558867999">"अनुप्रयोग बहु-विन्डोमा काम नगर्न सक्छ"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। सम्पादन गर्नका लागि डबल ट्याप गर्नुहोस्।"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। थप्नका लागि डबल ट्याप गर्नुहोस्।"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>। चयन गर्नका लागि डबल ट्याप गर्नुहोस्।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3cad1fae9ca7..41075e397ccc 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> sluiten."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwijderd."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle recente apps gesloten."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> starten."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Melding verwijderd."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startpagina"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Terug"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Meldingen"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Sneltoetsen"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Invoermethode schakelen"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Apps"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistentie"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacten"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muziek"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Weergeven met volumeknoppen"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Niet storen"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Volumeknoppen als sneltoets"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 91baa9b74215..1703a2fa630e 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਰੱਦ ਕਰੋ।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ਰੱਦ ਕੀਤਾ।"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ਸਾਰੀਆਂ ਹਾਲੀਆ ਐਪਲੀਕੇਸ਼ਨਾਂ ਰੱਦ ਕੀਤੀਆਂ।"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ਸੂਚਨਾ ਰੱਦ ਕੀਤੀ।"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ਮੁੱਖ ਸਕ੍ਰੀਨ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ਹਾਲੀਆ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ਪਿੱਛੇ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ਸੂਚਨਾਵਾਂ"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ਵਾਪਸ ਇਨਪੁੱਟ ਵਿਧੀ \'ਤੇ ਬਦਲੋ"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ਐਪਲੀਕੇਸ਼ਨਾਂ"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ਸਹਾਇਕ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ਬ੍ਰਾਊਜ਼ਰ"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ਸੰਪਰਕ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ਈਮੇਲ"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ਸੰਗੀਤ"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ਕੈਲੰਡਰ"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"ਵੌਲਯੂਮ ਕੰਟਰੋਲਾਂ ਨਾਲ ਵਿਖਾਓ"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ਵੌਲਯੂਮ ਬਟਨ ਸ਼ਾਰਟਕੱਟ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3aed4b25719e..297b849b14a3 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Usuń stąd <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>: zamknięto."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Wszystkie ostatnie aplikacje zostały zamknięte."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Uruchamiam <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Zamknięto powiadomienie."</string>
@@ -530,6 +532,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ekran główny"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Ostatnie"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Wstecz"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Powiadomienia"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Skróty klawiszowe"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Przełącz metodę wprowadzania"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacje"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoc"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Przeglądarka"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Komunikator"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzyka"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendarz"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Pokazuj z regulacją głośności"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nie przeszkadzać"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Wł./wył. przyciskami głośności"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 055a2981a9c6..eb08d997f064 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Início"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Voltar"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificações"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atalhos do teclado"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Alterar o método de entrada"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicativos"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistente"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatos"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mensagens instantâneas"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controles de volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não perturbe"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho de botões de volume"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f40c7c7fc234..bba2f3e63611 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ignorado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todas as aplicações recentes foram ignoradas."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A iniciar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação ignorada."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Página inicial"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Anterior"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificações"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atalhos de teclado"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Alternar o método de introdução"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicações"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistência"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendário"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controlos de volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não incomodar"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho dos botões de volume"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 055a2981a9c6..eb08d997f064 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Início"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Voltar"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificações"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atalhos do teclado"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Alterar o método de entrada"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicativos"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistente"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatos"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mensagens instantâneas"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controles de volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não perturbe"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho de botões de volume"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a307698fabf3..81d0456e5bda 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -169,6 +169,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Închideți <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> a fost eliminată."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toate aplicațiile recente au fost închise."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Se inițiază <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
@@ -529,6 +531,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ecran de pornire"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recente"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Înapoi"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificări"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Comenzi rapide de la tastatură"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Comutați metoda de introducere a textului"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicații"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistent"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Agendă"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzică"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Afișează cu comenzile de volum"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nu deranja"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Comandă rapidă din butoanele de volum"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 55216641baa9..86f0ec4c2ba9 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Удаление приложения <xliff:g id="APP">%s</xliff:g> из списка."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Все недавние приложения закрыты."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск приложения <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Уведомление закрыто"</string>
@@ -514,8 +516,8 @@
<string name="keyboard_key_backspace" msgid="1559580097512385854">"Backspace"</string>
<string name="keyboard_key_media_play_pause" msgid="3861975717393887428">"Воспроизведение/пауза"</string>
<string name="keyboard_key_media_stop" msgid="2859963958595908962">"Стоп"</string>
- <string name="keyboard_key_media_next" msgid="1894394911630345607">"Далее"</string>
- <string name="keyboard_key_media_previous" msgid="4256072387192967261">"Назад"</string>
+ <string name="keyboard_key_media_next" msgid="1894394911630345607">"Следующий трек"</string>
+ <string name="keyboard_key_media_previous" msgid="4256072387192967261">"Предыдущий трек"</string>
<string name="keyboard_key_media_rewind" msgid="2654808213360820186">"Перемотка назад"</string>
<string name="keyboard_key_media_fast_forward" msgid="3849417047738200605">"Перемотка вперед"</string>
<string name="keyboard_key_page_up" msgid="5654098530106845603">"Page Up"</string>
@@ -525,11 +527,23 @@
<string name="keyboard_key_move_end" msgid="5901174332047975247">"End"</string>
<string name="keyboard_key_insert" msgid="8530501581636082614">"Insert"</string>
<string name="keyboard_key_num_lock" msgid="5052537581246772117">"Num Lock"</string>
- <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"Цифровая клавиатура <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"<xliff:g id="NAME">%1$s</xliff:g> на цифровой панели"</string>
<string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"Система"</string>
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Главный экран"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Недавние"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Уведомления"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Быстрые клавиши"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Сменить способ ввода"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Приложения"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помощник"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузер"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакты"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Эл. почта"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка."</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календарь"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Показывать при нажатии кнопок регулировки громкости"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не беспокоить"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Кнопки регулировки громкости"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 61411d6b5e8d..5a2f849f3db3 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ඉවතලන්න."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලුම මෑත යෙඳුම් අස් කරන ලදි."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කරමින්."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්‍රභා කරඇත."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"මුල් පිටුව"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"මෑත"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ආපසු"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"දැනුම්දීම්"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"යතුරු පුවරු කෙටිමං"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ආදාන ක්‍රමය මාරු කිරීම"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"යෙදුම්"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"සහාය"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"බ්‍රවුසරය"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"සම්බන්ධතා"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ඊ-තැපෑල"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"සංගීතය"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"දින දර්ශනය"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"හඩ පරිමා පාලන සහිතව පෙන්වන්න"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"බාධා නොකරන්න"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"හඩ පරිමා බොත්තම් කෙටිමග"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f7967e339371..9468fcffb674 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zrušiť aplikáciu <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikácia <xliff:g id="APP">%s</xliff:g> bola zrušená."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všetky nedávne aplikácie boli odmietnuté."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spúšťa sa aplikácia <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Upozornenie bolo zrušené."</string>
@@ -530,6 +532,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Domovská stránka"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedávne"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Späť"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Upozornenia"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klávesové skratky"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Prepnúť metódu vstupu"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikácie"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomocná aplikácia"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Prehliadač"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Okamžité správy"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Hudba"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendár"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Zobrazovať s ovládacími prvkami hlasitosti"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nerušiť"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Skratka tlačidiel hlasitosti"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f0b7bc7e146a..c5a43f9f05da 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Opusti aplikacijo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je bila odstranjena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Vse nedavne aplikacije so bile opuščene."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Zaganjanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obvestilo je bilo odstranjeno."</string>
@@ -530,6 +532,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Začetni zaslon"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazaj"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obvestila"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Bližnjične tipke"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Preklop načina vnosa"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoč"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brskalnik"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Stiki"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Neposredno sporočanje"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Glasba"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Koledar"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži s kontrolniki glasnosti"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne moti"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Bližnjica z gumboma za glasnost"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 893e47190cd6..0188e5ba98d5 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Largo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> është hequr."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Të gjitha aplikacionet e fundit u larguan."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Po nis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Njoftimi është hequr."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Kreu"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Të fundit"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Prapa"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Njoftimet"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Shkurtoret e tastierës"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Ndërro metodën e hyrjes"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacionet"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistenti"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Shfletuesi"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktet"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Mail-i"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mesazh i çastit"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzikë"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendari"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Shfaq me kontrollet e volumit"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Mos shqetëso"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Shkurtorja e butonave të volumit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 6cfd7b04f0ba..501a3e346af9 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -169,6 +169,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Одбаците <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Апликација <xliff:g id="APP">%s</xliff:g> је одбачена."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Све недавно коришћене апликације су одбачене."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Покрећемо <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
@@ -529,6 +531,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Почетни"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Недавни садржај"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Обавештења"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Тастерске пречице"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Промени метод уноса"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Апликације"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Апликација за помоћ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Прегледач"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Имејл"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Размена тренутних порука"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Прикажи са контролама јачине звука"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не узнемиравај"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Пречица за дугмад за јачину звука"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6b1e949f8dce..959128e818b2 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ta bort <xliff:g id="APP">%s</xliff:g> från listan."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> togs bort permanent."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alla appar har tagits bort från listan Senaste."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Startar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Meddelandet ignorerades."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startsida"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Senaste"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tillbaka"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Aviseringar"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Kortkommandon"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Byt inmatningsmetod"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Appar"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Hjälp"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Webbläsare"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Snabbmeddelanden"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Visa med volymkontroller"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Stör ej"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Genväg till volymknappar"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 5acf6c022a2c..4b936c9b0dd9 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ondoa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> imeondolewa."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Programu za hivi majuzi zimeondolewa."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Inaanzisha <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Arifa imetupwa."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Mwanzo"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Zilizotumika majuzi"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nyuma"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Arifa"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Mikato ya Kibodi"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Badilisha mbinu ya kuingiza data"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Programu"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Programu ya maagizo ya sauti"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Kivinjari"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Anwani"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Barua pepe"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Ujumbe wa papo kwa papo"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muziki"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalenda"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Onyesha katika vidhibiti vya sauti"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Usinisumbue"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Njia ya mkato ya vitufe vya sauti"</string>
diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml
new file mode 100644
index 000000000000..08b2f8876470
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <integer name="quick_settings_num_rows">2</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml
new file mode 100644
index 000000000000..5ce65241c9ca
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <dimen name="qs_detail_items_padding_top">16dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-sw540dp/config.xml b/packages/SystemUI/res/values-sw540dp/config.xml
new file mode 100644
index 000000000000..e554fc6dd4d1
--- /dev/null
+++ b/packages/SystemUI/res/values-sw540dp/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <integer name="quick_settings_num_rows">3</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 4ed15d5c400b..49a7a299ec75 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -40,4 +40,8 @@
<dimen name="battery_detail_graph_space_top">27dp</dimen>
<dimen name="battery_detail_graph_space_bottom">27dp</dimen>
+
+ <dimen name="qs_tile_margin_top">16dp</dimen>
+ <dimen name="qs_brightness_padding_top">6dp</dimen>
+ <dimen name="qs_detail_margin_top">28dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 1c2f0deba5c1..5489be93b47f 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ஐ நிராகரி."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> விலக்கப்பட்டது."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"எல்லா சமீபத்திய பயன்பாடுகளும் விலக்கப்பட்டன."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ஐத் தொடங்குகிறது."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"அறிவிப்பு நிராகரிக்கப்பட்டது."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"முகப்பு"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"சமீபத்தியவை"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"முந்தையது"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"அறிவிப்புகள்"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"விசைப்பலகைக் குறுக்குவழிகள்"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"உள்ளீட்டு முறையை மாற்று"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"பயன்பாடுகள்"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"அசிஸ்ட்"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"உலாவி"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"தொடர்புகள்"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"மின்னஞ்சல்"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"மியூசிக்"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"கேலெண்டர்"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"ஒலிக் கட்டுப்பாடுகளுடன் காட்டு"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"தொந்தரவு செய்ய வேண்டாம்"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ஒலியளவுப் பொத்தான்களுக்கான குறுக்குவழி"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index bbefad299804..3a72809ac226 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ని తీసివేయండి."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> తీసివేయబడింది."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"అన్ని ఇటీవలి అనువర్తనాలు తీసివేయబడ్డాయి."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభిస్తోంది."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"నోటిఫికేషన్ తీసివేయబడింది."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"హోమ్"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ఇటీవలివి"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"వెనుకకు"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"నోటిఫికేషన్‌లు"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"కీబోర్డ్ సత్వరమార్గాలు"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ఇన్‌పుట్ పద్ధతిని మార్చండి"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"అనువర్తనాలు"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"సహాయకం"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"బ్రౌజర్"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"పరిచయాలు"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ఇమెయిల్"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"సంగీతం"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"క్యాలెండర్"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"వాల్యూమ్ నియంత్రణలతో చూపు"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"అంతరాయం కలిగించవద్దు"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"వాల్యూమ్ బటన్‌ల సత్వరమార్గం"</string>
@@ -588,8 +602,8 @@
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>. ఎంచుకోవడానికి రెండుసార్లు నొక్కండి."</string>
<string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలిస్తుంది"</string>
<string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తీసివేస్తుంది"</string>
- <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి జోడించబడింది"</string>
+ <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>వ స్థానానికి జోడించబడింది"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> తీసివేయబడింది"</string>
- <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి తరలించబడింది"</string>
+ <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>వ స్థానానికి తరలించబడింది"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"శీఘ్ర సెట్టింగ్‌ల ఎడిటర్."</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 809d425177a6..4844c843df6c 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ยกเลิก <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกลบไปแล้ว"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ปิดแอปพลิเคชันล่าสุดทั้งหมดแล้ว"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"กำลังเริ่มต้น <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"หน้าแรก"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ล่าสุด"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"กลับ"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"การแจ้งเตือน"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"แป้นพิมพ์ลัด"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"สลับวิธีการป้อนข้อมูล"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"แอปพลิเคชัน"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"การสนับสนุน"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"เบราว์เซอร์"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"รายชื่อติดต่อ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"อีเมล"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"เพลง"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ปฏิทิน"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"แสดงพร้อมการควบคุมระดับเสียง"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ห้ามรบกวน"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"ทางลัดปุ่มปรับระดับเสียง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 7e6ff8adf3f8..0672959fccba 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"I-dismiss ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Hindi pinansin ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Na-dismiss ang lahat ng kamakailang application."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Sinisimulan ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Na-dismiss ang notification."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Mga Kamakailang Ginamit"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Bumalik"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Mga Notification"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Mga Keyboard Shortcut"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Magpalit ng pamamaraan ng pag-input"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Mga Application"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Tulong"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Mga Contact"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendaryo"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Ipakita nang may mga kontrol ng volume"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Huwag istorbohin"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Shortcut ng mga button ng volume"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 05621a550c3a..58d488c50385 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> uygulamasını kapat."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> kaldırıldı."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tüm son uygulamalar kapatıldı."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlatılıyor."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildirim kapatıldı."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ana ekran"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Son çağrılar"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Geri"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Bildirimler"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klavye Kısayolları"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Giriş yöntemini değiştir"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Uygulamalar"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asist"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Tarayıcı"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kişiler"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-posta"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Müzik"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Takvim"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Ses seviyesi kontrolleriyle göster"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Rahatsız etmeyin"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Ses düğmeleri kısayolu"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index ac796491e32f..c75891c7d484 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -170,6 +170,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Видалити додаток <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Програму <xliff:g id="APP">%s</xliff:g> закрито."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усі останні додатки закрито."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск додатка <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Сповіщення відхилено."</string>
@@ -530,6 +532,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Головний екран"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Останні"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Сповіщення"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Комбінації клавіш"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Змінити метод введення"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Додатки"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помічник"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Веб-переглядач"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Електронна пошта"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Показувати регулятори гучності"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не турбувати"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Кнопки гучності на корпусі"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index a4a664b41de4..807a92379567 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> کو مسترد کریں۔"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> کو ہٹا دیا گیا۔"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"سبھی حالیہ ایپلیکیشنز کو برخاست کر دیا گیا۔"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> شروع ہو رہی ہے۔"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"اطلاع مسترد ہوگئی۔"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ہوم"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"حالیہ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"پیچھے"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"اطلاعات"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"کی بورڈ شارٹ کٹس"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"اندراج کا طریقہ سوئچ کریں"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ایپلیکیشنز"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"اسسٹ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"براؤزر"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"رابطے"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ای میل"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"موسیقی"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"کیلنڈر"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"والیوم کنٹرولز کے ساتھ دکھائیں"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ڈسٹرب نہ کریں"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"والیوم بٹنز کے شارٹ کٹ"</string>
@@ -591,5 +605,5 @@
<string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="POSITION">%2$d</xliff:g> پوزیشن پر <xliff:g id="TILE_NAME">%1$s</xliff:g> شامل ہو گیا ہے"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ہٹا دیا گیا"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="POSITION">%2$d</xliff:g> پوزیشن پر <xliff:g id="TILE_NAME">%1$s</xliff:g> منتقل ہو گیا ہے"</string>
- <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"فوری ترتیبات ایڈیٹر۔"</string>
+ <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"فوری ترتیبات کا ایڈیٹر۔"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index f5bcc3dde6b9..fe67b527f913 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Olib tashlash: <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> olib tashlangan."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Yaqinda ishlatilgan barcha ilovalar olib tashlandi."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ishga tushirilmoqda."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Xabarnoma e‘tiborsiz qoldirildi."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Bosh ekran"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"So‘nggi ishlatilganlar"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Orqaga"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Bildirishnomalar"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tezkor tugmalar"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Matn kiritish usulini o‘zgartirish"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Ilovalar"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Yordamchi"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauzer"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktlar"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pochta"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiqa"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Taqvim"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Ovoz balandligini boshqarish tugmalari bilan ko‘rsatish"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Bezovta qilinmasin"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Ovoz balandligini boshqarish tugmalari"</string>
@@ -563,7 +577,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Klaviatura tugmasini tanlang"</string>
<string name="preview" msgid="9077832302472282938">"Oldindan ko‘rish"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Fragmentlar qo‘shish uchun torting"</string>
- <string name="drag_to_remove_tiles" msgid="3361212377437088062">"O‘chirish uchun bu yerga sudrang"</string>
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"O‘chirish uchun bu yerga torting"</string>
<string name="qs_edit" msgid="2232596095725105230">"Tahrirlash"</string>
<string name="tuner_time" msgid="6572217313285536011">"Vaqt"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index ed3e8f369c5b..ca7c59b72663 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Xóa bỏ <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã bỏ qua tất cả các ứng dụng gần đây."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Bắt đầu <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Màn hình chính"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Gần đây"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Quay lại"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Thông báo"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Phím tắt"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Chuyển phương thức nhập"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Ứng dụng"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Trợ lý"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Trình duyệt"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Danh bạ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Nhắn tin nhanh"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Âm nhạc"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Lịch"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Hiển thị với các điều khiển âm lượng"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Không làm phiền"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Phím tắt các nút âm lượng"</string>
diff --git a/packages/SystemUI/res/values-w550dp-land/dimens.xml b/packages/SystemUI/res/values-w550dp-land/dimens.xml
index cd17bedcec32..4160c83683cc 100644
--- a/packages/SystemUI/res/values-w550dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-w550dp-land/dimens.xml
@@ -20,7 +20,4 @@
<dimen name="notification_panel_width">544dp</dimen>
<dimen name="qs_expand_margin">32dp</dimen>
-
- <dimen name="battery_detail_graph_space_top">9dp</dimen>
- <dimen name="battery_detail_graph_space_bottom">9dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 3b0c02302b3d..a25b9f125cc2 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -34,14 +34,14 @@
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
<string name="battery_low_title" msgid="6456385927409742437">"电池电量偏低"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
- <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>。节电助手已开启。"</string>
+ <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>。省电模式已开启。"</string>
<string name="invalid_charger" msgid="4549105996740522523">"不支持USB充电功能。\n只能使用随附的充电器充电。"</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"不支持USB充电。"</string>
<string name="invalid_charger_text" msgid="5474997287953892710">"仅限使用设备随附的充电器。"</string>
<string name="battery_low_why" msgid="4553600287639198111">"设置"</string>
- <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"要开启节电助手吗?"</string>
+ <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"要开启省电模式吗?"</string>
<string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"开启"</string>
- <string name="battery_saver_start_action" msgid="5576697451677486320">"开启节电助手"</string>
+ <string name="battery_saver_start_action" msgid="5576697451677486320">"开启省电模式"</string>
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string>
<string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自动旋转屏幕"</string>
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"移除<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"已删除<xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"已关闭所有最近用过的应用。"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在启动<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
@@ -371,9 +373,9 @@
<string name="user_remove_user_title" msgid="4681256956076895559">"是否移除用户?"</string>
<string name="user_remove_user_message" msgid="1453218013959498039">"此用户的所有应用和数据均将被删除。"</string>
<string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
- <string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已开启"</string>
+ <string name="battery_saver_notification_title" msgid="237918726750955859">"省电模式已开启"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"降低性能并限制后台流量"</string>
- <string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭节电助手"</string>
+ <string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭省电模式"</string>
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>将开始截取您的屏幕上显示的所有内容。"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"不再显示"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string>
@@ -495,8 +497,8 @@
<string name="color_revert_title" msgid="4746666545480534663">"确认设置"</string>
<string name="color_revert_message" msgid="9116001069397996691">"部分颜色设置可能会导致此设备无法使用。请点击“确定”确认这些颜色设置,否则,系统将在 10 秒后重置这些设置。"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string>
- <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用节电助手"</string>
- <string name="battery_detail_switch_title" msgid="6285872470260795421">"节电助手"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用省电模式"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"省电模式"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低性能并限制后台流量"</string>
<string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g>按钮"</string>
<string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主屏幕"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"键盘快捷键"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"切换输入法"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"应用"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"辅助应用"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"浏览器"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"通讯录"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"电子邮件"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即时通讯"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音乐"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日历"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"与音量控件一起显示"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"请勿打扰"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"音量按钮快捷键"</string>
@@ -583,7 +597,7 @@
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"左移"</string>
<string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"右移"</string>
<string name="forced_resizable_info_text" msgid="7591061837558867999">"应用可能无法在多窗口模式下正常运行"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按再次即可修改。"</string>
+ <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按两次即可修改。"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。点按两次即可添加。"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。点按两次即可选择。"</string>
<string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"移动<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
@@ -591,5 +605,5 @@
<string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"已将<xliff:g id="TILE_NAME">%1$s</xliff:g>添加到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"已移除<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"已将<xliff:g id="TILE_NAME">%1$s</xliff:g>移至位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快速设置编辑器。"</string>
+ <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快捷设置编辑器。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index dc4a6dd90a67..083cd5eb035d 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式均已關閉。"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g><xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知已關閉。"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主畫面"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近的活動"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"鍵盤快速鍵"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"切換輸入法"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"應用程式"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"輔助"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"瀏覽器"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"通訊錄"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"電郵"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即時通訊"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音樂"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日曆"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"與音量控制一起顯示"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"請勿騷擾"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"音量按鈕快速鍵"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 72ff27c8b942..3c95a9397cc6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的應用程式已全部關閉。"</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主畫面"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"近期活動"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"鍵盤快速鍵"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"切換輸入法"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"應用程式"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"小幫手"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"瀏覽器"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"聯絡人"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"電子郵件"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即時訊息"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音樂"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日曆"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"與音量控制項一起顯示"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"零打擾"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"音量按鈕快速鍵"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 2eb96813c126..e03e6422ca22 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -168,6 +168,8 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Cashisa i-<xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ivaliwe."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Zonke izinhlelo zokusebenza zakamuva zicashisiwe."</string>
+ <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+ <skip />
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iqala i-<xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Isaziso sichithiwe."</string>
@@ -528,6 +530,18 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ekhaya"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Okwakamuva"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Emuva"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Izaziso"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Izinqamulelo Zekhibhodi"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Shintsha indlela yokufaka"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Izinhlelo zokusebenza"</string>
+ <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Siza"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Isiphequluli"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Oxhumana nabo"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"I-imeyili"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"I-IM"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Umculo"</string>
+ <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"I-YouTube"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Ikhalenda"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Bonisa ngezilawuli zevolomu"</string>
<string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ungaphazamisi"</string>
<string name="volume_dnd_silent" msgid="4363882330723050727">"Izinqamuleli zezinkinobho zevolomu"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 1e979fda17bd..6dd8c5260b89 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -97,5 +97,9 @@
<declare-styleable name="DensityContainer">
<attr name="android:layout" />
</declare-styleable>
+
+ <declare-styleable name="AutoSizingList">
+ <attr name="itemHeight" format="dimension" />
+ </declare-styleable>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index b9aa26b0c785..b874e7c051db 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -169,6 +169,8 @@
<color name="ksh_system_group_color">#ff00bcd4</color>
<color name="ksh_application_group_color">#fff44336</color>
<color name="ksh_keyword_color">#d9000000</color>
+ <color name="ksh_key_item_color">@color/material_grey_600</color>
+ <color name="ksh_key_item_background">#eeeeee</color>
<!-- Background color of edit overflow -->
<color name="qs_edit_overflow_bg">#455A64</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index fd051b1b371f..42798a49b3af 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -92,11 +92,8 @@
<!-- The number of columns in the QuickSettings -->
<integer name="quick_settings_num_columns">3</integer>
- <!-- The maximum number of rows in the QuickSettings -->
- <integer name="quick_settings_max_rows">4</integer>
-
- <!-- The maximum number of rows in the QuickSettings when on the keyguard -->
- <integer name="quick_settings_max_rows_keyguard">3</integer>
+ <!-- The number of rows in the QuickSettings -->
+ <integer name="quick_settings_num_rows">1</integer>
<!-- The number of columns that the top level tiles span in the QuickSettings -->
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
@@ -116,9 +113,6 @@
<integer name="quick_settings_brightness_dialog_short_timeout">2000</integer>
<integer name="quick_settings_brightness_dialog_long_timeout">4000</integer>
- <!-- The maximum number of items to be displayed in quick settings -->
- <integer name="quick_settings_detail_max_item_count">5</integer>
-
<!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
<bool name="config_show4GForLTE">true</bool>
@@ -178,7 +172,7 @@
<!-- Recents: The relative range of visible tasks from the current scroll position
while the stack is focused. -->
<item name="recents_layout_focused_range_min" format="float" type="integer">-3</item>
- <item name="recents_layout_focused_range_max" format="float" type="integer">3</item>
+ <item name="recents_layout_focused_range_max" format="float" type="integer">2</item>
<!-- Recents: The relative range of visible tasks from the current scroll position
while the stack is not focused. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c094da9db43a..a4eadbfb5601 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -172,6 +172,7 @@
<dimen name="qs_tile_height">88dp</dimen>
<dimen name="qs_tile_margin">16dp</dimen>
+ <dimen name="qs_tile_margin_top">16dp</dimen>
<dimen name="qs_quick_tile_size">48dp</dimen>
<dimen name="qs_quick_tile_padding">12dp</dimen>
<dimen name="qs_date_anim_translation">32dp</dimen>
@@ -201,10 +202,12 @@
<dimen name="qs_detail_item_primary_text_size">16sp</dimen>
<dimen name="qs_detail_item_secondary_text_size">14sp</dimen>
<dimen name="qs_detail_empty_text_size">14sp</dimen>
+ <dimen name="qs_detail_margin_top">28dp</dimen>
<dimen name="qs_data_usage_text_size">14sp</dimen>
<dimen name="qs_data_usage_usage_text_size">36sp</dimen>
<dimen name="qs_expand_margin">0dp</dimen>
<dimen name="qs_battery_padding">2dp</dimen>
+ <dimen name="qs_detail_items_padding_top">4dp</dimen>
<dimen name="segmented_button_spacing">0dp</dimen>
<dimen name="borderless_button_radius">2dp</dimen>
@@ -561,6 +564,9 @@
<!-- Keyboard shortcuts helper -->
<dimen name="ksh_layout_width">@dimen/match_parent</dimen>
+ <dimen name="ksh_item_text_size">14sp</dimen>
+ <dimen name="ksh_item_padding">4dp</dimen>
+ <dimen name="ksh_item_margin_start">4dp</dimen>
<!-- Recents Layout -->
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index 337513d4daea..4e6a4b1b8212 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -54,5 +54,7 @@
<!-- Extra space around the PIP and its outline in PIP onboarding activity -->
<dimen name="tv_pip_bounds_space">3dp</dimen>
+ <!-- Extra space around the PIP control button icon to match with the focused circle -->
+ <dimen name="tv_pip_button_icon_padding">5dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a01066d70262..060e050ed97c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -417,6 +417,8 @@
<string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> dismissed.</string>
<!-- Content description to tell the user all applications has been removed from recents -->
<string name="accessibility_recents_all_items_dismissed">All recent applications dismissed.</string>
+ <!-- Content description to tell the user that this button will open application info for an application in recents -->
+ <string name="accessibility_recents_item_open_app_info">Open <xliff:g id="app" example="Calendar">%s</xliff:g> application info.</string>
<!-- Content description to tell the user an application has been launched from recents -->
<string name="accessibility_recents_item_launched">Starting <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
<!-- Content description of individual recents task. -->
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index aa3f6e5fe4a3..d12ab293ab3e 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -514,7 +514,7 @@ public class ExpandHelper implements Gefingerpoken {
if (canBeExpanded) {
if (DEBUG) Log.d(TAG, "working on an expandable child");
mNaturalHeight = mScaler.getNaturalHeight();
- mSmallSize = v.getMinExpandHeight();
+ mSmallSize = v.getCollapsedHeight();
} else {
if (DEBUG) Log.d(TAG, "working on a non-expandable child");
mNaturalHeight = mOldHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/ResizingSpace.java b/packages/SystemUI/src/com/android/systemui/ResizingSpace.java
new file mode 100644
index 000000000000..c2bc53e7d553
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ResizingSpace.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT 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;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+public class ResizingSpace extends View {
+
+ private final int mWidth;
+ private final int mHeight;
+
+ public ResizingSpace(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ if (getVisibility() == VISIBLE) {
+ setVisibility(INVISIBLE);
+ }
+ TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ViewGroup_Layout);
+ mWidth = a.getResourceId(android.R.styleable.ViewGroup_Layout_layout_width, 0);
+ mHeight = a.getResourceId(android.R.styleable.ViewGroup_Layout_layout_height, 0);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ LayoutParams params = getLayoutParams();
+ boolean changed = false;
+ if (mWidth > 0) {
+ int width = getContext().getResources().getDimensionPixelOffset(mWidth);
+ if (width != params.width) {
+ params.width = width;
+ changed = true;
+ }
+ }
+ if (mHeight > 0) {
+ int height = getContext().getResources().getDimensionPixelOffset(mHeight);
+ if (height != params.height) {
+ params.height = height;
+ changed = true;
+ }
+ }
+ if (changed) {
+ setLayoutParams(params);
+ }
+ }
+
+ /**
+ * Draw nothing.
+ *
+ * @param canvas an unused parameter.
+ */
+ @Override
+ public void draw(Canvas canvas) {
+ }
+
+ /**
+ * Compare to: {@link View#getDefaultSize(int, int)}
+ * If mode is AT_MOST, return the child size instead of the parent size
+ * (unless it is too big).
+ */
+ private static int getDefaultSize2(int size, int measureSpec) {
+ int result = size;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ switch (specMode) {
+ case MeasureSpec.UNSPECIFIED:
+ result = size;
+ break;
+ case MeasureSpec.AT_MOST:
+ result = Math.min(size, specSize);
+ break;
+ case MeasureSpec.EXACTLY:
+ result = specSize;
+ break;
+ }
+ return result;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(
+ getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
+ getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 8f79bdabedc9..e83819179c24 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -325,10 +325,11 @@ public class SwipeHelper implements Gefingerpoken {
/**
* @param view The view to be dismissed
* @param velocity The desired pixels/second speed at which the view should move
+ * @param useAccelerateInterpolator Should an accelerating Interpolator be used
*/
- public void dismissChild(final View view, float velocity) {
+ public void dismissChild(final View view, float velocity, boolean useAccelerateInterpolator) {
dismissChild(view, velocity, null /* endAction */, 0 /* delay */,
- velocity == 0 /* useAccelerateInterpolator */, 0 /* fixedDuration */);
+ useAccelerateInterpolator, 0 /* fixedDuration */, false /* isDismissAll */);
}
/**
@@ -340,17 +341,22 @@ public class SwipeHelper implements Gefingerpoken {
* @param fixedDuration If not 0, this exact duration will be taken
*/
public void dismissChild(final View animView, float velocity, final Runnable endAction,
- long delay, boolean useAccelerateInterpolator, long fixedDuration) {
+ long delay, boolean useAccelerateInterpolator, long fixedDuration,
+ boolean isDismissAll) {
final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
float newPos;
boolean isLayoutRtl = animView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- if (velocity < 0
- || (velocity == 0 && getTranslation(animView) < 0)
- // if we use the Menu to dismiss an item in landscape, animate up
- || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)
- // if the language is rtl we prefer swiping to the left
- || (velocity == 0 && getTranslation(animView) == 0 && isLayoutRtl)) {
+ // if we use the Menu to dismiss an item in landscape, animate up
+ boolean animateUpForMenu = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
+ && mSwipeDirection == Y;
+ // if the language is rtl we prefer swiping to the left
+ boolean animateLeftForRtl = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
+ && isLayoutRtl;
+ boolean animateLeft = velocity < 0
+ || (velocity == 0 && getTranslation(animView) < 0 && !isDismissAll);
+
+ if (animateLeft || animateLeftForRtl || animateUpForMenu) {
newPos = -getSize(animView);
} else {
newPos = getSize(animView);
@@ -569,7 +575,8 @@ public class SwipeHelper implements Gefingerpoken {
if (!handleUpEvent(ev, mCurrView, velocity, getTranslation(mCurrView))) {
if (isDismissGesture(ev)) {
// flingadingy
- dismissChild(mCurrView, swipedFastEnough() ? velocity : 0f);
+ dismissChild(mCurrView, velocity,
+ !swipedFastEnough() /* useAccelerateInterpolator */);
} else {
// snappity
mCallback.onDragCancelled(mCurrView);
@@ -615,11 +622,9 @@ public class SwipeHelper implements Gefingerpoken {
protected boolean swipedFastEnough() {
float velocity = getVelocity(mVelocityTracker);
- float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
float translation = getTranslation(mCurrView);
- boolean ret = (Math.abs(velocity) > getEscapeVelocity()) &&
- (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
- (velocity > 0) == (translation > 0);
+ boolean ret = (Math.abs(velocity) > getEscapeVelocity())
+ && (velocity > 0) == (translation > 0);
return ret;
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index b2b612787fd2..455a69fcc77b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -123,6 +123,17 @@ public class SystemUIApplication extends Application {
startServicesIfNeeded(SERVICES);
}
+ /**
+ * Ensures that all the Secondary user SystemUI services are running. If they are already
+ * running, this is a no-op. This is needed to conditinally start all the services, as we only
+ * need to have it in the main process.
+ *
+ * <p>This method must only be called from the main thread.</p>
+ */
+ void startSecondaryUserServicesIfNeeded() {
+ startServicesIfNeeded(SERVICES_PER_USER);
+ }
+
private void startServicesIfNeeded(Class<?>[] services) {
if (mServicesStarted) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
new file mode 100644
index 000000000000..f619bfbcd047
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.app.ActivityManager;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Process;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public class SystemUISecondaryUserService extends Service {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ ((SystemUIApplication) getApplication()).startSecondaryUserServicesIfNeeded();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
+ if (args == null || args.length == 0) {
+ for (SystemUI ui: services) {
+ pw.println("dumping service: " + ui.getClass().getName());
+ ui.dump(fd, pw, args);
+ }
+ } else {
+ String svc = args[0];
+ for (SystemUI ui: services) {
+ String name = ui.getClass().getName();
+ if (name.endsWith(svc)) {
+ ui.dump(fd, pw, args);
+ }
+ }
+ }
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index d2c60efd1282..84d359926c50 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -115,9 +115,9 @@ public class KeyguardService extends Service {
}
@Override // Binder interface
- public void onFinishedGoingToSleep(int reason) {
+ public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {
checkPermission();
- mKeyguardViewMediator.onFinishedGoingToSleep(reason);
+ mKeyguardViewMediator.onFinishedGoingToSleep(reason, cameraGestureTriggered);
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a5dfc4b2ad85..66754a7fa80c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -747,7 +747,7 @@ public class KeyguardViewMediator extends SystemUI {
notifyStartedGoingToSleep();
}
- public void onFinishedGoingToSleep(int why) {
+ public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")");
synchronized (this) {
mDeviceInteractive = false;
@@ -758,6 +758,16 @@ public class KeyguardViewMediator extends SystemUI {
notifyFinishedGoingToSleep();
+ if (cameraGestureTriggered) {
+ Log.i(TAG, "Camera gesture was triggered, preventing Keyguard locking.");
+
+ // Just to make sure, make sure the device is awake.
+ mContext.getSystemService(PowerManager.class).wakeUp(SystemClock.uptimeMillis(),
+ "com.android.systemui:CAMERA_GESTURE_PREVENT_LOCK");
+ mPendingLock = false;
+ mPendingReset = false;
+ }
+
if (mPendingReset) {
resetStateLocked();
mPendingReset = false;
@@ -771,7 +781,7 @@ public class KeyguardViewMediator extends SystemUI {
// We do not have timeout and power button instant lock setting for profile lock.
// So we use the personal setting if there is any. But if there is no device
// we need to make sure we lock it immediately when the screen is off.
- if (!mLockLater) {
+ if (!mLockLater && !cameraGestureTriggered) {
doKeyguardForChildProfilesLocked();
}
@@ -794,7 +804,7 @@ public class KeyguardViewMediator extends SystemUI {
// From DevicePolicyAdmin
final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
- .getMaximumTimeToLock(null, userId);
+ .getMaximumTimeToLockForUserAndProfiles(userId);
long timeout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
new file mode 100644
index 000000000000..00e62213ff46
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT 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.qs;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import com.android.systemui.R;
+
+/**
+ * Similar to a ListView, but it will show only as many items as fit on screen and
+ * bind those instead of scrolling.
+ */
+public class AutoSizingList extends LinearLayout {
+
+ private static final String TAG = "AutoSizingList";
+ private final int mItemSize;
+ private final Handler mHandler;
+
+ private ListAdapter mAdapter;
+ private int mCount;
+
+ public AutoSizingList(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+
+ mHandler = new Handler();
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoSizingList);
+ mItemSize = a.getDimensionPixelSize(R.styleable.AutoSizingList_itemHeight, 0);
+ }
+
+ public void setAdapter(ListAdapter adapter) {
+ if (mAdapter != null) {
+ mAdapter.unregisterDataSetObserver(mDataObserver);
+ }
+ mAdapter = adapter;
+ if (adapter != null) {
+ adapter.registerDataSetObserver(mDataObserver);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
+ if (requestedHeight != 0) {
+ int count = Math.min(requestedHeight / mItemSize, getDesiredCount());
+ if (mCount != count) {
+ postRebindChildren();
+ mCount = count;
+ }
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ private int getDesiredCount() {
+ return mAdapter != null ? mAdapter.getCount() : 0;
+ }
+
+ private void postRebindChildren() {
+ mHandler.post(mBindChildren);
+ }
+
+ private void rebindChildren() {
+ if (mAdapter == null) {
+ return;
+ }
+ for (int i = 0; i < mCount; i++) {
+ View v = i < getChildCount() ? getChildAt(i) : null;
+ View newView = mAdapter.getView(i, v, this);
+ if (newView != v) {
+ if (v != null) {
+ removeView(v);
+ }
+ addView(newView, i);
+ }
+ }
+ // Ditch extra views.
+ while (getChildCount() > mCount) {
+ removeViewAt(getChildCount() - 1);
+ }
+ }
+
+ private final Runnable mBindChildren = new Runnable() {
+ @Override
+ public void run() {
+ rebindChildren();
+ }
+ };
+
+ private final DataSetObserver mDataObserver = new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ if (mCount > getDesiredCount()) {
+ mCount = getDesiredCount();
+ }
+ postRebindChildren();
+ }
+
+ @Override
+ public void onInvalidated() {
+ postRebindChildren();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 115c9d0e06fb..5a236104806f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -1,6 +1,8 @@
package com.android.systemui.qs;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
@@ -199,11 +201,22 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
@Override
public boolean updateResources() {
- if (super.updateResources()) {
- mMaxRows = mColumns != 3 ? 2 : 3;
- return true;
+ final int rows = getRows();
+ boolean changed = rows != mMaxRows;
+ if (changed) {
+ mMaxRows = rows;
+ requestLayout();
}
- return false;
+ return super.updateResources() || changed;
+ }
+
+ private int getRows() {
+ final Resources res = getContext().getResources();
+ if (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ // Always have 3 rows in portrait.
+ return 3;
+ }
+ return Math.max(1, res.getInteger(R.integer.quick_settings_num_rows));
}
public void setMaxRows(int maxRows) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index 5d06aebdba66..0af5fa62d219 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -100,7 +100,13 @@ public class QSContainer extends FrameLayout {
// Since we control our own bottom, be whatever size we want.
// Otherwise the QSPanel ends up with 0 height when the window is only the
// size of the status bar.
- super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
+ mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(
+ MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED));
+ int width = mQSPanel.getMeasuredWidth();
+ int height = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+ + mQSPanel.getMeasuredHeight();
+ super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
// QSCustomizer is always be the height of the screen, but do this after
// other measuring to avoid changing the height of the QSContainer.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index 25b91054af89..2dd4a0ab76eb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -28,11 +28,10 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
-
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
@@ -45,16 +44,17 @@ public class QSDetailItems extends FrameLayout {
private final Context mContext;
private final H mHandler = new H();
+ private final Adapter mAdapter = new Adapter();
private String mTag;
private Callback mCallback;
private boolean mItemsVisible = true;
- private LinearLayout mItems;
+ private AutoSizingList mItemList;
private View mEmpty;
- private View mMinHeightSpacer;
private TextView mEmptyText;
private ImageView mEmptyIcon;
- private int mMaxItems;
+
+ private Item[] mItems;
public QSDetailItems(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -73,27 +73,22 @@ public class QSDetailItems extends FrameLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mItems = (LinearLayout) findViewById(android.R.id.list);
- mItems.setVisibility(GONE);
+ mItemList = (AutoSizingList) findViewById(android.R.id.list);
+ mItemList.setVisibility(GONE);
+ mItemList.setAdapter(mAdapter);
mEmpty = findViewById(android.R.id.empty);
mEmpty.setVisibility(GONE);
mEmptyText = (TextView) mEmpty.findViewById(android.R.id.title);
mEmptyIcon = (ImageView) mEmpty.findViewById(android.R.id.icon);
- mMinHeightSpacer = findViewById(R.id.min_height_spacer);
-
- // By default, a detail item view has fixed size.
- mMaxItems = getResources().getInteger(
- R.integer.quick_settings_detail_max_item_count);
- setMinHeightInItems(mMaxItems);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
- int count = mItems.getChildCount();
+ int count = mItemList.getChildCount();
for (int i = 0; i < count; i++) {
- View item = mItems.getChildAt(i);
+ View item = mItemList.getChildAt(i);
FontSizeUtils.updateFontSize(item, android.R.id.title,
R.dimen.qs_detail_item_primary_text_size);
FontSizeUtils.updateFontSize(item, android.R.id.summary,
@@ -110,16 +105,6 @@ public class QSDetailItems extends FrameLayout {
mEmptyText.setText(text);
}
- /**
- * Set the minimum height of this detail view, in item count.
- */
- public void setMinHeightInItems(int minHeightInItems) {
- ViewGroup.LayoutParams lp = mMinHeightSpacer.getLayoutParams();
- lp.height = minHeightInItems * getResources().getDimensionPixelSize(
- R.dimen.qs_detail_item_height);
- mMinHeightSpacer.setLayoutParams(lp);
- }
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -153,65 +138,82 @@ public class QSDetailItems extends FrameLayout {
}
private void handleSetItems(Item[] items) {
- final int itemCount = items != null ? Math.min(items.length, mMaxItems) : 0;
+ final int itemCount = items != null ? items.length : 0;
mEmpty.setVisibility(itemCount == 0 ? VISIBLE : GONE);
- mItems.setVisibility(itemCount == 0 ? GONE : VISIBLE);
- for (int i = mItems.getChildCount() - 1; i >= itemCount; i--) {
- mItems.removeViewAt(i);
- }
- for (int i = 0; i < itemCount; i++) {
- bind(items[i], mItems.getChildAt(i));
- }
+ mItemList.setVisibility(itemCount == 0 ? GONE : VISIBLE);
+ mItems = items;
+ mAdapter.notifyDataSetChanged();
}
private void handleSetItemsVisible(boolean visible) {
if (mItemsVisible == visible) return;
mItemsVisible = visible;
- for (int i = 0; i < mItems.getChildCount(); i++) {
- mItems.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
+ for (int i = 0; i < mItemList.getChildCount(); i++) {
+ mItemList.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
}
}
- private void bind(final Item item, View view) {
- if (view == null) {
- view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, this, false);
- mItems.addView(view);
+ private class Adapter extends BaseAdapter {
+
+ @Override
+ public int getCount() {
+ return mItems != null ? mItems.length : 0;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mItems[position];
}
- view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
- final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
- iv.setImageResource(item.icon);
- iv.getOverlay().clear();
- if (item.overlay != null) {
- item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
- item.overlay.getIntrinsicHeight());
- iv.getOverlay().add(item.overlay);
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
}
- final TextView title = (TextView) view.findViewById(android.R.id.title);
- title.setText(item.line1);
- final TextView summary = (TextView) view.findViewById(android.R.id.summary);
- final boolean twoLines = !TextUtils.isEmpty(item.line2);
- title.setMaxLines(twoLines ? 1 : 2);
- summary.setVisibility(twoLines ? VISIBLE : GONE);
- summary.setText(twoLines ? item.line2 : null);
- view.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mCallback != null) {
- mCallback.onDetailItemClick(item);
- }
+
+ @Override
+ public View getView(int position, View view, ViewGroup parent) {
+ final Item item = mItems[position];
+ if (view == null) {
+ view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, parent,
+ false);
}
- });
- final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
- disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
- disconnect.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mCallback != null) {
- mCallback.onDetailItemDisconnect(item);
- }
+ view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
+ final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
+ iv.setImageResource(item.icon);
+ iv.getOverlay().clear();
+ if (item.overlay != null) {
+ item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
+ item.overlay.getIntrinsicHeight());
+ iv.getOverlay().add(item.overlay);
}
- });
- }
+ final TextView title = (TextView) view.findViewById(android.R.id.title);
+ title.setText(item.line1);
+ final TextView summary = (TextView) view.findViewById(android.R.id.summary);
+ final boolean twoLines = !TextUtils.isEmpty(item.line2);
+ title.setMaxLines(twoLines ? 1 : 2);
+ summary.setVisibility(twoLines ? VISIBLE : GONE);
+ summary.setText(twoLines ? item.line2 : null);
+ view.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onDetailItemClick(item);
+ }
+ }
+ });
+ final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
+ disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
+ disconnect.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onDetailItemDisconnect(item);
+ }
+ }
+ });
+ return view;
+ }
+ };
private class H extends Handler {
private static final int SET_ITEMS = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 98a1c23aa645..57a1a4a09a10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -37,7 +37,7 @@ public class QSTileView extends QSTileBaseView {
private final int mTileSpacingPx;
private int mTilePaddingTopPx;
- private TextView mLabel;
+ protected TextView mLabel;
private ImageView mPadLock;
public QSTileView(Context context, QSIconView icon) {
@@ -81,7 +81,7 @@ public class QSTileView extends QSTileBaseView {
FontSizeUtils.updateFontSize(mLabel, R.dimen.qs_tile_text_size);
}
- private void createLabel() {
+ protected void createLabel() {
final Resources res = mContext.getResources();
View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null);
mLabel = (TextView) view.findViewById(R.id.tile_label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 55eda9838664..6969e25d0a61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -24,6 +24,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
private int mCellMargin;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+ private int mCellMarginTop;
public TileLayout(Context context) {
this(context, null);
@@ -60,9 +61,10 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
mCellMargin = res.getDimensionPixelSize(R.dimen.qs_tile_margin);
+ mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
if (mColumns != columns) {
mColumns = columns;
- postInvalidate();
+ requestLayout();
return true;
}
return false;
@@ -81,7 +83,8 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
previousView = record.tileView.updateAccessibilityOrder(previousView);
}
- setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows);
+ setMeasuredDimension(width,
+ (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin));
}
private static int exactly(int size) {
@@ -114,7 +117,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
}
private int getRowTop(int row) {
- return row * (mCellHeight + mCellMargin) + mCellMargin;
+ return row * (mCellHeight + mCellMargin) + mCellMarginTop;
}
private int getColumnStart(int column) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
new file mode 100644
index 000000000000..e512f93f2ced
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT 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.qs.customize;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSIconView;
+import com.android.systemui.qs.QSTileView;
+import libcore.util.Objects;
+
+public class CustomizeTileView extends QSTileView {
+
+ private TextView mAppLabel;
+
+ public CustomizeTileView(Context context, QSIconView icon) {
+ super(context, icon);
+ }
+
+ @Override
+ protected void createLabel() {
+ super.createLabel();
+ View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null);
+ mAppLabel = (TextView) view.findViewById(R.id.tile_label);
+ mAppLabel.setAlpha(.6f);
+ mAppLabel.setSingleLine(true);
+ addView(view);
+ }
+
+ public void setShowAppLabel(boolean showAppLabel) {
+ mAppLabel.setVisibility(showAppLabel ? View.VISIBLE : View.GONE);
+ mLabel.setSingleLine(showAppLabel);
+ }
+
+ public void setAppLabel(CharSequence label) {
+ if (!Objects.equal(label, mAppLabel.getText())) {
+ mAppLabel.setText(label);
+ }
+ }
+
+ public TextView getAppLabel() {
+ return mAppLabel;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 4c134516f844..e8e17b1d15c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -41,7 +41,6 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto;
import com.android.systemui.R;
import com.android.systemui.qs.QSIconView;
-import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.customize.TileAdapter.Holder;
import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
@@ -61,6 +60,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private static final int TYPE_TILE = 0;
private static final int TYPE_EDIT = 1;
private static final int TYPE_ACCESSIBLE_DROP = 2;
+ private static final int TYPE_DIVIDER = 4;
+
+ private static final long EDIT_ID = 10000;
+ private static final long DIVIDER_ID = 20000;
private final Context mContext;
@@ -68,7 +71,8 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private final List<TileInfo> mTiles = new ArrayList<>();
private final ItemTouchHelper mItemTouchHelper;
private final AccessibilityManager mAccessibilityManager;
- private int mDividerIndex;
+ private int mEditIndex;
+ private int mTileDividerIndex;
private boolean mNeedsFocus;
private List<String> mCurrentSpecs;
private List<TileInfo> mOtherTiles;
@@ -87,7 +91,8 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
@Override
public long getItemId(int position) {
- return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position)) : -1;
+ return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position))
+ : position == mEditIndex ? EDIT_ID : DIVIDER_ID;
}
public ItemTouchHelper getItemTouchHelper() {
@@ -100,7 +105,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
public void saveSpecs(QSTileHost host) {
List<String> newSpecs = new ArrayList<>();
- for (int i = 0; mTiles.get(i) != null; i++) {
+ for (int i = 0; i < mTiles.size() && mTiles.get(i) != null; i++) {
newSpecs.add(mTiles.get(i).spec);
}
host.changeTiles(mCurrentSpecs, newSpecs);
@@ -131,8 +136,19 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
}
mTiles.add(null);
+ for (int i = 0; i < mOtherTiles.size(); i++) {
+ final TileInfo tile = mOtherTiles.get(i);
+ if (tile.isSystem) {
+ mOtherTiles.remove(i--);
+ mTiles.add(tile);
+ }
+ }
+ if (mOtherTiles.size() != 0) {
+ mTileDividerIndex = mTiles.size();
+ mTiles.add(null);
+ }
mTiles.addAll(mOtherTiles);
- mDividerIndex = mTiles.indexOf(null);
+ mEditIndex = mTiles.indexOf(null);
notifyDataSetChanged();
}
@@ -147,9 +163,12 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
@Override
public int getItemViewType(int position) {
- if (mAccessibilityMoving && position == mDividerIndex - 1) {
+ if (mAccessibilityMoving && position == mEditIndex - 1) {
return TYPE_ACCESSIBLE_DROP;
}
+ if (position == mTileDividerIndex) {
+ return TYPE_DIVIDER;
+ }
if (mTiles.get(position) == null) {
return TYPE_EDIT;
}
@@ -160,12 +179,15 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
final Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
+ if (viewType == TYPE_DIVIDER) {
+ return new Holder(inflater.inflate(R.layout.qs_customize_tile_divider, parent, false));
+ }
if (viewType == TYPE_EDIT) {
return new Holder(inflater.inflate(R.layout.qs_customize_divider, parent, false));
}
FrameLayout frame = (FrameLayout) inflater.inflate(R.layout.qs_customize_tile_frame, parent,
false);
- frame.addView(new QSTileView(context, new QSIconView(context)));
+ frame.addView(new CustomizeTileView(context, new QSIconView(context)));
return new Holder(frame);
}
@@ -176,6 +198,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
@Override
public void onBindViewHolder(final Holder holder, final int position) {
+ if (holder.getItemViewType() == TYPE_DIVIDER) {
+ return;
+ }
if (holder.getItemViewType() == TYPE_EDIT) {
((TextView) holder.itemView.findViewById(android.R.id.title)).setText(
mCurrentDrag != null ? R.string.drag_to_remove_tiles
@@ -213,7 +238,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
TileInfo info = mTiles.get(position);
- if (position > mDividerIndex) {
+ if (position > mEditIndex) {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_add_tile_label, info.state.label);
} else if (mAccessibilityMoving) {
@@ -224,9 +249,11 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
R.string.accessibility_qs_edit_tile_label, position + 1, info.state.label);
}
holder.mTileView.onStateChanged(info.state);
+ holder.mTileView.setAppLabel(info.appLabel);
+ holder.mTileView.setShowAppLabel(position > mTileDividerIndex);
if (mAccessibilityManager.isTouchExplorationEnabled()) {
- final boolean selectable = !mAccessibilityMoving || position < mDividerIndex;
+ final boolean selectable = !mAccessibilityMoving || position < mEditIndex;
holder.mTileView.setClickable(selectable);
holder.mTileView.setFocusable(selectable);
holder.mTileView.setImportantForAccessibility(selectable
@@ -239,7 +266,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
if (mAccessibilityMoving) {
selectPosition(position, v);
} else {
- if (position < mDividerIndex) {
+ if (position < mEditIndex) {
showAccessibilityDialog(position, v);
} else {
startAccessibleDrag(position);
@@ -253,7 +280,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private void selectPosition(int position, View v) {
// Remove the placeholder.
- mTiles.remove(mDividerIndex--);
+ mTiles.remove(mEditIndex--);
mAccessibilityMoving = false;
move(mAccessibilityFromIndex, position, v);
notifyDataSetChanged();
@@ -272,7 +299,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
if (which == 0) {
startAccessibleDrag(position);
} else {
- move(position, mDividerIndex, v);
+ move(position, mEditIndex, v);
}
}
}).setNegativeButton(android.R.string.cancel, null)
@@ -287,7 +314,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mNeedsFocus = true;
mAccessibilityFromIndex = position;
// Add placeholder for last slot.
- mTiles.add(mDividerIndex++, null);
+ mTiles.add(mEditIndex++, null);
notifyDataSetChanged();
}
@@ -296,25 +323,38 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
private boolean move(int from, int to, View v) {
- if (to > mDividerIndex) {
- if (from >= mDividerIndex) {
+ if (to >= mEditIndex) {
+ if (from >= mEditIndex) {
return false;
}
+ // Sort tiles into system/non-system groups.
+ TileInfo tile = mTiles.get(from);
+ if (tile.isSystem) {
+ if (to > mTileDividerIndex) {
+ to = mTileDividerIndex;
+ }
+ } else {
+ if (mTileDividerIndex == mTiles.size()) {
+ mTiles.add(null);
+ }
+ if (to <= mTileDividerIndex) {
+ to = mTileDividerIndex;
+ }
+ }
}
CharSequence fromLabel = mTiles.get(from).state.label;
move(from, to, mTiles);
- mDividerIndex = mTiles.indexOf(null);
- notifyItemChanged(from);
- notifyItemMoved(from, to);
+ notifyDataSetChanged();
+ updateDividerLocations();
CharSequence announcement;
- if (to >= mDividerIndex) {
+ if (to >= mEditIndex) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE,
from);
announcement = mContext.getString(R.string.accessibility_qs_edit_tile_removed,
fromLabel);
- } else if (from >= mDividerIndex) {
+ } else if (from >= mEditIndex) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD,
@@ -333,6 +373,25 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
return true;
}
+ private void updateDividerLocations() {
+ // The first null is the edit tiles label, the second null is the tile divider.
+ // If there is no second null, then there are no non-system tiles.
+ mEditIndex = -1;
+ mTileDividerIndex = mTiles.size();
+ for (int i = 0; i < mTiles.size(); i++) {
+ if (mTiles.get(i) == null) {
+ if (mEditIndex == -1) {
+ mEditIndex = i;
+ } else {
+ mTileDividerIndex = i;
+ }
+ }
+ }
+ if (mTiles.get(mTiles.size() - 1) == null) {
+ mTiles.remove(mTiles.size() - 1);
+ }
+ }
+
private String strip(TileInfo tileInfo) {
String spec = tileInfo.spec;
if (spec.startsWith(CustomTile.PREFIX)) {
@@ -348,12 +407,12 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
public class Holder extends ViewHolder {
- private QSTileView mTileView;
+ private CustomizeTileView mTileView;
public Holder(View itemView) {
super(itemView);
if (itemView instanceof FrameLayout) {
- mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0);
+ mTileView = (CustomizeTileView) ((FrameLayout) itemView).getChildAt(0);
mTileView.setBackground(null);
mTileView.getIcon().disableAnimation();
}
@@ -367,6 +426,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mTileView.findViewById(R.id.tile_label).animate()
.setDuration(DRAG_LENGTH)
.alpha(0);
+ mTileView.getAppLabel().animate()
+ .setDuration(DRAG_LENGTH)
+ .alpha(0);
}
public void stopDrag() {
@@ -377,13 +439,17 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mTileView.findViewById(R.id.tile_label).animate()
.setDuration(DRAG_LENGTH)
.alpha(1);
+ mTileView.getAppLabel().animate()
+ .setDuration(DRAG_LENGTH)
+ .alpha(.6f);
}
}
private final SpanSizeLookup mSizeLookup = new SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
- return getItemViewType(position) == TYPE_EDIT ? 3 : 1;
+ final int type = getItemViewType(position);
+ return type == TYPE_EDIT || type == TYPE_DIVIDER ? 3 : 1;
}
};
@@ -401,7 +467,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final ViewHolder holder = parent.getChildViewHolder(child);
- if (holder.getAdapterPosition() < mDividerIndex) {
+ if (holder.getAdapterPosition() < mEditIndex) {
continue;
}
@@ -443,7 +509,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mHandler.post(new Runnable() {
@Override
public void run() {
- notifyItemChanged(mDividerIndex);
+ notifyItemChanged(mEditIndex);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index bbc885691b31..d04a2fc7e148 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -31,6 +31,7 @@ import android.service.quicksettings.TileService;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTile.DrawableIcon;
+import com.android.systemui.qs.QSTile.State;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -79,7 +80,7 @@ public class TileQueryHelper {
mainHandler.post(new Runnable() {
@Override
public void run() {
- addTile(spec, state);
+ addTile(spec, null, state, true);
mListener.onTilesChanged(mTiles);
}
});
@@ -103,28 +104,33 @@ public class TileQueryHelper {
mListener = listener;
}
- private void addTile(String spec, QSTile.State state) {
+ private void addTile(String spec, CharSequence appLabel, State state, boolean isSystem) {
if (mSpecs.contains(spec)) {
return;
}
TileInfo info = new TileInfo();
info.state = state;
info.spec = spec;
+ info.appLabel = appLabel;
+ info.isSystem = isSystem;
mTiles.add(info);
mSpecs.add(spec);
}
- private void addTile(String spec, Drawable drawable, CharSequence label, Context context) {
+ private void addTile(String spec, Drawable drawable, CharSequence label, CharSequence appLabel,
+ Context context) {
QSTile.State state = new QSTile.State();
state.label = label;
state.contentDescription = label;
state.icon = new DrawableIcon(drawable);
- addTile(spec, state);
+ addTile(spec, appLabel, state, false);
}
public static class TileInfo {
public String spec;
+ public CharSequence appLabel;
public QSTile.State state;
+ public boolean isSystem;
}
private class QueryTilesTask extends AsyncTask<Void, Void, Collection<TileInfo>> {
@@ -147,7 +153,8 @@ public class TileQueryHelper {
icon.setTint(mContext.getColor(android.R.color.white));
}
CharSequence label = info.serviceInfo.loadLabel(pm);
- addTile(spec, icon, label != null ? label.toString() : "null", mContext);
+ final CharSequence appLabel = info.serviceInfo.applicationInfo.loadLabel(pm);
+ addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
}
return tiles;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 1fef8f18cd39..63c85dbd6c37 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -216,7 +216,6 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
R.string.quick_settings_bluetooth_detail_empty_text);
mItems.setCallback(this);
- mItems.setMinHeightInItems(0);
updateItems();
setItemsVisible(mState.value);
return mItems;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 8060e07801bb..b1d955573d19 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -78,6 +78,9 @@ import com.android.systemui.recents.views.RecentsView;
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.statusbar.BaseStatusBar;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* The main Recents activity that is started from AlternateRecentsComponent.
*/
@@ -733,4 +736,20 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
});
return true;
}
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ super.dump(prefix, fd, writer, args);
+ String id = Integer.toHexString(System.identityHashCode(this));
+
+ writer.print(prefix); writer.print(TAG);
+ writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N");
+ writer.print(" [0x"); writer.print(id); writer.print("]");
+ writer.println();
+
+ if (mRecentsView != null) {
+ mRecentsView.dump(prefix, writer);
+ }
+ EventBus.getDefault().dump(prefix, writer);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 4dae7460f30a..aba05aa38619 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -144,7 +144,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Task launching
Rect mTaskStackBounds = new Rect();
- Rect mLastTaskViewBounds = new Rect();
TaskViewTransform mTmpTransform = new TaskViewTransform();
int mStatusBarHeight;
int mNavBarHeight;
@@ -169,8 +168,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
});
- protected Bitmap mThumbnailTransitionBitmapCache;
- Task mThumbnailTransitionBitmapCacheKey;
+ protected Bitmap mThumbTransitionBitmapCache;
public RecentsImpl(Context context) {
mContext = context;
@@ -186,7 +184,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Initialize the static configuration resources
reloadHeaderBarLayout();
- updateHeaderBarLayout(null /* stack */);
// When we start, preload the data associated with the previous recent tasks.
// We can use a new plan since the caches will be the same.
@@ -201,12 +198,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
public void onBootCompleted() {
- updateHeaderBarLayout(null /* stack */);
+ // Do nothing
}
public void onConfigurationChanged() {
reloadHeaderBarLayout();
- updateHeaderBarLayout(null /* stack */);
}
/**
@@ -368,9 +364,14 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
loader.preloadTasks(sInstanceLoadPlan, topTask.id, topTaskHome.value);
TaskStack stack = sInstanceLoadPlan.getTaskStack();
if (stack.getTaskCount() > 0) {
- // We try and draw the thumbnail transition bitmap in parallel before
- // toggle/show recents is called
- preCacheThumbnailTransitionBitmapAsync(topTask, stack, mDummyStackView);
+ // Only preload the icon (but not the thumbnail since it may not have been taken for
+ // the pausing activity)
+ preloadIcon(topTask);
+
+ // At this point, we don't know anything about the stack state. So only calculate
+ // the dimensions of the thumbnail that we need for the transition into Recents, but
+ // do not draw it until we construct the activity options when we start Recents
+ updateHeaderBarLayout(stack);
}
}
}
@@ -601,21 +602,30 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
if (stack != null) {
stackLayout.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
mTaskStackBounds);
+ stackLayout.reset();
stackLayout.initialize(windowRect, mTaskStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
- }
- Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
- if (!taskViewBounds.equals(mLastTaskViewBounds)) {
- mLastTaskViewBounds.set(taskViewBounds);
+ Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
int taskViewWidth = taskViewBounds.width();
synchronized (mHeaderBarLock) {
- mHeaderBar.measure(
- View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY),
- View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY));
+ if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
+ mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
+ mHeaderBar.measure(
+ View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY));
+ }
mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
}
+
+ // Update the transition bitmap to match the new header bar height
+ if (mThumbTransitionBitmapCache == null ||
+ (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
+ (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
+ mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
+ mTaskBarHeight, Bitmap.Config.ARGB_8888);
+ }
}
}
@@ -652,40 +662,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
/**
- * Caches the header thumbnail used for a window animation asynchronously into
- * {@link #mThumbnailTransitionBitmapCache}.
- */
- private void preCacheThumbnailTransitionBitmapAsync(ActivityManager.RunningTaskInfo topTask,
- TaskStack stack, TaskStackView stackView) {
- preloadIcon(topTask);
-
- // Update the header bar if necessary
- updateHeaderBarLayout(stack);
-
- // Update the destination rect
- final Task toTask = new Task();
- final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
- ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
- @Override
- public void run() {
- final Bitmap transitionBitmap = drawThumbnailTransitionBitmap(toTask, toTransform);
- if (transitionBitmap != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mThumbnailTransitionBitmapCache = transitionBitmap;
- mThumbnailTransitionBitmapCacheKey = toTask;
- }
- });
- } else {
- Log.e(TAG, "Could not load thumbnail for task: " + toTask + " at transform: " +
- toTransform);
- }
- }
- });
- }
-
- /**
* Creates the activity options for a unknown state->recents transition.
*/
protected ActivityOptions getUnknownTransitionActivityOptions() {
@@ -724,9 +700,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
if (task.isFreeformTask()) {
mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
stackScroller.getStackScroll(), mTmpTransform, null);
+ Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform,
+ mThumbTransitionBitmapCache);
Rect toTaskRect = new Rect();
mTmpTransform.rect.round(toTaskRect);
- Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect));
}
}
@@ -738,9 +715,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Update the destination rect
Task toTask = new Task();
TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
- RectF toTaskRect = toTransform.rect;
- Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform);
+ Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
+ mThumbTransitionBitmapCache);
if (thumbnail != null) {
+ RectF toTaskRect = toTransform.rect;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
thumbnail, (int) toTaskRect.left, (int) toTaskRect.top,
(int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null);
@@ -750,22 +728,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
}
- private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask,
- TaskViewTransform toTransform) {
- Bitmap thumbnail;
- if (mThumbnailTransitionBitmapCacheKey != null
- && mThumbnailTransitionBitmapCacheKey.key != null
- && mThumbnailTransitionBitmapCacheKey.key.equals(toTask.key)) {
- thumbnail = mThumbnailTransitionBitmapCache;
- mThumbnailTransitionBitmapCacheKey = null;
- mThumbnailTransitionBitmapCache = null;
- } else {
- preloadIcon(topTask);
- thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform);
- }
- return thumbnail;
- }
-
/**
* Returns the transition rect for the given task id.
*/
@@ -793,26 +755,19 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
/**
* Draws the header of a task used for the window animation into a bitmap.
*/
- private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform) {
+ private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform,
+ Bitmap thumbnail) {
SystemServicesProxy ssp = Recents.getSystemServices();
if (toTransform != null && toTask.key != null) {
- Bitmap thumbnail;
synchronized (mHeaderBarLock) {
- int toHeaderWidth = (int) toTransform.rect.width();
- int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
- if (toHeaderWidth <= 0 || toHeaderHeight <= 0) {
- return null;
- }
boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode();
mHeaderBar.onTaskViewSizeChanged((int) toTransform.rect.width(),
(int) toTransform.rect.height());
- thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
- Bitmap.Config.ARGB_8888);
if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
thumbnail.eraseColor(0xFFff0000);
} else {
+ thumbnail.eraseColor(0);
Canvas c = new Canvas(thumbnail);
- c.scale(toTransform.scale, toTransform.scale);
// Workaround for b/27815919, reset the callback so that we do not trigger an
// invalidate on the header bar as a result of updating the icon
Drawable icon = mHeaderBar.getIconView().getDrawable();
@@ -854,6 +809,18 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
boolean hasRecentTasks = stack.getTaskCount() > 0;
boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
+ // Update the launch state that we need in updateHeaderBarLayout()
+ launchState.launchedFromHome = !useThumbnailTransition;
+ launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
+ launchState.launchedViaDockGesture = mLaunchedWhileDocking;
+ launchState.launchedViaDragGesture = mDraggingInRecents;
+ launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
+ launchState.launchedWithAltTab = mTriggeredFromAltTab;
+
+ // Preload the icon (this will be a null-op if we have preloaded the icon already in
+ // preloadRecents())
+ preloadIcon(topTask);
+
// Update the header bar if necessary
updateHeaderBarLayout(stack);
@@ -861,44 +828,27 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
TaskStackLayoutAlgorithm.VisibilityReport stackVr =
mDummyStackView.computeStackVisibilityReport();
- // Update the launch state
- launchState.launchedFromHome = false;
- launchState.launchedFromApp = mLaunchedWhileDocking;
- launchState.launchedViaDockGesture = mLaunchedWhileDocking;
- launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
- launchState.launchedWithAltTab = mTriggeredFromAltTab;
+ // Update the remaining launch state
launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks;
launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails;
- launchState.launchedViaDragGesture = mDraggingInRecents;
if (!animate) {
startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1));
return;
}
+ ActivityOptions opts;
if (useThumbnailTransition) {
- launchState.launchedFromApp = true;
-
// Try starting with a thumbnail transition
- ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
- if (opts != null) {
- startRecentsActivity(opts);
- } else {
- // Fall through below to the non-thumbnail transition
- useThumbnailTransition = false;
- }
- }
-
- if (!useThumbnailTransition) {
- launchState.launchedFromHome = true;
-
+ opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
+ } else {
// If there is no thumbnail transition, but is launching from home into recents, then
// use a quick home transition
- ActivityOptions opts = hasRecentTasks
- ? getHomeTransitionActivityOptions()
- : getUnknownTransitionActivityOptions();
- startRecentsActivity(opts);
+ opts = hasRecentTasks
+ ? getHomeTransitionActivityOptions()
+ : getUnknownTransitionActivityOptions();
}
+ startRecentsActivity(opts);
mLastToggleTime = SystemClock.elapsedRealtime();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
index 0d56ae98a165..38ad1c710716 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -30,6 +30,7 @@ import android.util.MutableBoolean;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
+import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -652,19 +653,43 @@ public class EventBus extends BroadcastReceiver {
/**
* @return a dump of the current state of the EventBus
*/
- public String dump() {
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(dumpInternal(prefix));
+ }
+
+ public String dumpInternal(String prefix) {
+ String innerPrefix = prefix + " ";
+ String innerInnerPrefix = innerPrefix + " ";
StringBuilder output = new StringBuilder();
+ output.append(prefix);
output.append("Registered class types:");
output.append("\n");
- for (Class<?> clz : mSubscriberTypeMap.keySet()) {
- output.append("\t");
+ ArrayList<Class<?>> subsciberTypes = new ArrayList<>(mSubscriberTypeMap.keySet());
+ Collections.sort(subsciberTypes, new Comparator<Class<?>>() {
+ @Override
+ public int compare(Class<?> o1, Class<?> o2) {
+ return o1.getSimpleName().compareTo(o2.getSimpleName());
+ }
+ });
+ for (int i = 0; i < subsciberTypes.size(); i++) {
+ Class<?> clz = subsciberTypes.get(i);
+ output.append(innerPrefix);
output.append(clz.getSimpleName());
output.append("\n");
}
+ output.append(prefix);
output.append("Event map:");
output.append("\n");
- for (Class<?> clz : mEventTypeMap.keySet()) {
- output.append("\t");
+ ArrayList<Class<?>> classes = new ArrayList<>(mEventTypeMap.keySet());
+ Collections.sort(classes, new Comparator<Class<?>>() {
+ @Override
+ public int compare(Class<?> o1, Class<?> o2) {
+ return o1.getSimpleName().compareTo(o2.getSimpleName());
+ }
+ });
+ for (int i = 0; i < classes.size(); i++) {
+ Class<?> clz = classes.get(i);
+ output.append(innerPrefix);
output.append(clz.getSimpleName());
output.append(" -> ");
output.append("\n");
@@ -673,7 +698,7 @@ public class EventBus extends BroadcastReceiver {
Object subscriber = handler.subscriber.getReference();
if (subscriber != null) {
String id = Integer.toHexString(System.identityHashCode(subscriber));
- output.append("\t\t");
+ output.append(innerInnerPrefix);
output.append(subscriber.getClass().getSimpleName());
output.append(" [0x" + id + ", #" + handler.priority + "]");
output.append("\n");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index e28612a3cff6..69d98af5a2b2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -243,4 +243,14 @@ public class Utilities {
public static float dpToPx(Resources res, float dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
}
+
+ /**
+ * Returns a lightweight dump of a rect.
+ */
+ public static String dumpRect(Rect r) {
+ if (r == null) {
+ return "N:0,0-0,0";
+ }
+ return r.left + "," + r.top + "-" + r.right + "," + r.bottom;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 76ca6ca3bba9..7aeff1feca71 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -132,6 +132,8 @@ public class RecentsTaskLoadPlan {
SparseIntArray affiliatedTaskCounts = new SparseIntArray();
String dismissDescFormat = mContext.getString(
R.string.accessibility_recents_item_will_be_dismissed);
+ String appInfoDescFormat = mContext.getString(
+ R.string.accessibility_recents_item_open_app_info);
long lastStackActiveTime = Prefs.getLong(mContext,
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
if (RecentsDebugFlags.Static.EnableMockTasks) {
@@ -188,8 +190,9 @@ public class RecentsTaskLoadPlan {
// Load the title, icon, and color
ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
- String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
- String dismissDescription = String.format(dismissDescFormat, contentDescription);
+ String titleDescription = loader.getAndUpdateContentDescription(taskKey, res);
+ String dismissDescription = String.format(dismissDescFormat, titleDescription);
+ String appInfoDescription = String.format(appInfoDescFormat, titleDescription);
Drawable icon = isStackTask
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
: null;
@@ -201,9 +204,9 @@ public class RecentsTaskLoadPlan {
// Add the task to the stack
Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
- thumbnail, title, contentDescription, dismissDescription, activityColor,
- backgroundColor, isLaunchTarget, isStackTask, isSystemApp, t.isDockable,
- t.bounds, t.taskDescription);
+ thumbnail, title, titleDescription, dismissDescription, appInfoDescription,
+ activityColor, backgroundColor, isLaunchTarget, isStackTask, isSystemApp,
+ t.isDockable, t.bounds, t.taskDescription);
allTasks.add(task);
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index d5d5aa0dc97f..24eeaf27f032 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -29,6 +29,7 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
@@ -37,6 +38,9 @@ import java.util.Objects;
* A task represents the top most task in the system's task stack.
*/
public class Task {
+
+ public static final String TAG = "Task";
+
/* Task callbacks */
public interface TaskCallbacks {
/* Notifies when a task has been bound */
@@ -100,7 +104,8 @@ public class Task {
@Override
public String toString() {
- return "t" + id + ", s" + stackId + ", u" + userId;
+ return "id=" + id + " stackId=" + stackId + " user=" + userId + " lastActiveTime=" +
+ lastActiveTime;
}
private void updateHashCode() {
@@ -134,10 +139,12 @@ public class Task {
@ViewDebug.ExportedProperty(category="recents")
public String title;
@ViewDebug.ExportedProperty(category="recents")
- public String contentDescription;
+ public String titleDescription;
@ViewDebug.ExportedProperty(category="recents")
public String dismissDescription;
@ViewDebug.ExportedProperty(category="recents")
+ public String appInfoDescription;
+ @ViewDebug.ExportedProperty(category="recents")
public int colorPrimary;
@ViewDebug.ExportedProperty(category="recents")
public int colorBackground;
@@ -174,8 +181,8 @@ public class Task {
}
public Task(TaskKey key, int affiliationTaskId, int affiliationColor, Drawable icon,
- Bitmap thumbnail, String title, String contentDescription,
- String dismissDescription, int colorPrimary, int colorBackground,
+ Bitmap thumbnail, String title, String titleDescription, String dismissDescription,
+ String appInfoDescription, int colorPrimary, int colorBackground,
boolean isLaunchTarget, boolean isStackTask, boolean isSystemApp,
boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription) {
boolean isInAffiliationGroup = (affiliationTaskId != key.id);
@@ -186,8 +193,9 @@ public class Task {
this.icon = icon;
this.thumbnail = thumbnail;
this.title = title;
- this.contentDescription = contentDescription;
+ this.titleDescription = titleDescription;
this.dismissDescription = dismissDescription;
+ this.appInfoDescription = appInfoDescription;
this.colorPrimary = hasAffiliationGroupColor ? affiliationColor : colorPrimary;
this.colorBackground = colorBackground;
this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
@@ -211,8 +219,9 @@ public class Task {
this.icon = o.icon;
this.thumbnail = o.thumbnail;
this.title = o.title;
- this.contentDescription = o.contentDescription;
+ this.titleDescription = o.titleDescription;
this.dismissDescription = o.dismissDescription;
+ this.appInfoDescription = o.appInfoDescription;
this.colorPrimary = o.colorPrimary;
this.colorBackground = o.colorBackground;
this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
@@ -302,4 +311,13 @@ public class Task {
public String toString() {
return "[" + key.toString() + "] " + title;
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ writer.print(prefix); writer.print(key);
+ if (affiliationTaskId != key.id) {
+ writer.print(" "); writer.print("affTaskId=" + affiliationTaskId);
+ }
+ writer.print(" "); writer.print(title);
+ writer.println();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index df3f56c7c3ac..fbb59870b237 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -55,6 +55,7 @@ import com.android.systemui.recents.views.AnimationProps;
import com.android.systemui.recents.views.DropTarget;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -208,6 +209,8 @@ class FilteredTaskList {
*/
public class TaskStack {
+ private static final String TAG = "TaskStack";
+
/** Task stack callbacks */
public interface TaskStackCallbacks {
/**
@@ -725,7 +728,9 @@ public class TaskStack {
/** Finds the task with the specified task id. */
public Task findTaskWithId(int taskId) {
ArrayList<Task> tasks = computeAllTasksList();
- for (Task task : tasks) {
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ Task task = tasks.get(i);
if (task.key.id == taskId) {
return task;
}
@@ -880,7 +885,10 @@ public class TaskStack {
ArraySet<ComponentName> existingComponents = new ArraySet<>();
ArraySet<ComponentName> removedComponents = new ArraySet<>();
ArrayList<Task.TaskKey> taskKeys = getTaskKeys();
- for (Task.TaskKey t : taskKeys) {
+ int taskKeyCount = taskKeys.size();
+ for (int i = 0; i < taskKeyCount; i++) {
+ Task.TaskKey t = taskKeys.get(i);
+
// Skip if this doesn't apply to the current user
if (t.userId != userId) continue;
@@ -903,8 +911,10 @@ public class TaskStack {
@Override
public String toString() {
String str = "Stack Tasks (" + mStackTaskList.size() + "):\n";
- for (Task t : mStackTaskList.getTasks()) {
- str += " " + t.toString() + "\n";
+ ArrayList<Task> tasks = mStackTaskList.getTasks();
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ str += " " + tasks.get(i).toString() + "\n";
}
return str;
}
@@ -921,4 +931,17 @@ public class TaskStack {
}
return map;
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+
+ writer.print(prefix); writer.print(TAG);
+ writer.print(" numStackTasks="); writer.print(mStackTaskList.size());
+ writer.println();
+ ArrayList<Task> tasks = mStackTaskList.getTasks();
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ tasks.get(i).dump(innerPrefix, writer);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index 483f9e523c55..f9f851a76c2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -53,7 +53,6 @@ import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.tv.animations.FocusAnimationHolder;
import com.android.systemui.recents.tv.views.RecentsTvView;
import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -79,7 +78,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
private boolean mIgnoreAltTabRelease;
private RecentsTvView mRecentsView;
- private FocusAnimationHolder mRecentsFocusAnimationHolder;
private View mPipView;
private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
private FinishRecentsRunnable mFinishLaunchHomeRunnable;
@@ -133,13 +131,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
- if (hasFocus) {
- mRecentsFocusAnimationHolder.startFocusLoseAnimation();
- mPipRecentsOverlayManager.requestFocus(
- mTaskStackViewAdapter.getItemCount() > 0);
- } else {
- mRecentsFocusAnimationHolder.startFocusGainAnimation();
- }
+ handlePipViewFocusChange(hasFocus);
}
};
@@ -288,11 +280,10 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- mRecentsFocusAnimationHolder = new FocusAnimationHolder(mRecentsView);
mPipView = findViewById(R.id.pip);
// Place mPipView at the PIP bounds for fine tuned focus handling.
- Rect pipBounds = mPipManager.getPipBounds();
+ Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
lp.width = pipBounds.width();
lp.height = pipBounds.height();
@@ -513,11 +504,30 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
if (mPipManager.isPipShown()) {
mPipView.setVisibility(View.VISIBLE);
mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
- mPipView.requestFocus();
+ if (mPipView.hasFocus()) {
+ // This can happen only if the activity is resumed. Ask for reset.
+ handlePipViewFocusChange(true);
+ } else {
+ mPipView.requestFocus();
+ }
} else {
mPipView.setVisibility(View.GONE);
mPipRecentsOverlayManager.removePipRecentsOverlayView();
- mRecentsFocusAnimationHolder.reset();
+ }
+ }
+
+ /**
+ * Handles the PIP view's focus change.
+ * This starts the relevant recents row animation
+ * and give focus to the recents overlay if needed.
+ */
+ private void handlePipViewFocusChange(boolean hasFocus) {
+ mRecentsView.startRecentsRowFocusAnimation(!hasFocus);
+ if (hasFocus) {
+ // When PIP view has focus, recents overlay view will takes the focus
+ // as if it's the part of the Recents UI.
+ mPipRecentsOverlayManager.requestFocus(
+ mTaskStackViewAdapter.getItemCount() > 0);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
index c1b47dcbb4e0..fb62affd6cee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
@@ -124,7 +124,7 @@ public class RecentsTvImpl extends RecentsImpl{
*/
private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
ActivityManager.RunningTaskInfo topTask) {
- Bitmap thumbnail = mThumbnailTransitionBitmapCache;
+ Bitmap thumbnail = mThumbTransitionBitmapCache;
Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
if (thumbnail != null) {
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/FocusAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/FocusAnimationHolder.java
deleted file mode 100644
index 864540c616e9..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/FocusAnimationHolder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.recents.tv.animations;
-
-import android.content.res.Resources;
-import android.view.View;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.tv.views.TaskCardView;
-
-/**
- * Collections of Recents row's animation depending on the PIP's focus.
- */
-public class FocusAnimationHolder {
- private final float DIM_ALPHA = 0.5f;
-
- private View mRecentsRowView;
- private int mCardYDelta;
- private long mDuration;
-
- public FocusAnimationHolder(View recentsRowView) {
- mRecentsRowView = recentsRowView;
-
- Resources res = recentsRowView.getResources();
- mCardYDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_shift_down);
- mDuration = res.getInteger(R.integer.recents_tv_pip_focus_anim_duration);
- }
-
- public void startFocusGainAnimation() {
- mRecentsRowView.animate()
- .setDuration(mDuration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .alpha(1f)
- .translationY(0);
- }
-
- public void startFocusLoseAnimation() {
- mRecentsRowView.animate()
- .setDuration(mDuration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .alpha(DIM_ALPHA)
- .translationY(mCardYDelta);
- }
-
- public void reset() {
- mRecentsRowView.setTransitionAlpha(1f);
- mRecentsRowView.setTranslationY(0);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
new file mode 100644
index 000000000000..28abc344f7d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv.animations;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.view.View;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+/**
+ * Recents row's focus animation with PIP controls.
+ */
+public class RecentsRowFocusAnimationHolder {
+ private static final float DIM_ALPHA = 0.5f;
+
+ private View mView;
+ private View mTitleView;
+
+ private AnimatorSet mFocusGainAnimatorSet;
+ private AnimatorSet mFocusLoseAnimatorSet;
+
+ public RecentsRowFocusAnimationHolder(View view, View titleView) {
+ mView = view;
+ mTitleView = titleView;
+
+ Resources res = view.getResources();
+ int duration = res.getInteger(R.integer.recents_tv_pip_focus_anim_duration);
+
+ mFocusGainAnimatorSet = new AnimatorSet();
+ mFocusGainAnimatorSet.playTogether(
+ ObjectAnimator.ofFloat(mView, "alpha", 1f),
+ ObjectAnimator.ofFloat(mTitleView, "alpha", 1f));
+ mFocusGainAnimatorSet.setDuration(duration);
+ mFocusGainAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+
+ mFocusLoseAnimatorSet = new AnimatorSet();
+ mFocusLoseAnimatorSet.playTogether(
+ ObjectAnimator.ofFloat(mView, "alpha", DIM_ALPHA),
+ ObjectAnimator.ofFloat(mTitleView, "alpha", 0f));
+ mFocusLoseAnimatorSet.setDuration(duration);
+ mFocusLoseAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ }
+
+ /**
+ * Returns the Recents row's focus change animation.
+ */
+ public Animator getFocusChangeAnimator(boolean hasFocus) {
+ return hasFocus ? mFocusGainAnimatorSet : mFocusLoseAnimatorSet;
+ }
+
+ /**
+ * Resets the views to the initial state immediately.
+ */
+ public void reset() {
+ mView.setAlpha(1f);
+ mTitleView.setAlpha(1f);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
index d966614efb1b..9da8eed3996b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -37,6 +37,7 @@ import com.android.systemui.recents.events.component.RecentsVisibilityChangedEve
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
import java.util.ArrayList;
import java.util.List;
@@ -52,6 +53,7 @@ public class RecentsTvView extends FrameLayout {
private TaskStack mStack;
private TaskStackHorizontalGridView mTaskStackHorizontalView;
private View mEmptyView;
+ private RecentsRowFocusAnimationHolder mEmptyViewFocusAnimationHolder;
private boolean mAwaitingFirstLayout = true;
private Rect mSystemInsets = new Rect();
private RecentsTvTransitionHelper mTransitionHelper;
@@ -77,6 +79,8 @@ public class RecentsTvView extends FrameLayout {
LayoutInflater inflater = LayoutInflater.from(context);
mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
addView(mEmptyView);
+ mEmptyViewFocusAnimationHolder = new RecentsRowFocusAnimationHolder(mEmptyView, null);
+
mHandler = new Handler();
mTransitionHelper = new RecentsTvTransitionHelper(mContext, mHandler);
}
@@ -94,7 +98,6 @@ public class RecentsTvView extends FrameLayout {
mTaskStackHorizontalView.setStack(stack);
}
-
if (stack.getStackTaskCount() > 0) {
hideEmptyView();
} else {
@@ -134,33 +137,40 @@ public class RecentsTvView extends FrameLayout {
public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
if (mTaskStackHorizontalView != null) {
// Iterate the stack views and try and find the given task.
- List<TaskCardView> taskViews = mTaskStackHorizontalView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int j = 0; j < taskViewCount; j++) {
- TaskCardView tv = taskViews.get(j);
- if (tv.getTask() == task) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
- return true;
- }
+ if (mTaskStackHorizontalView.getChildViewForTask(task) != null) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
+ return true;
}
}
return false;
}
/**
+ * Starts the focus change animation.
+ */
+ public void startRecentsRowFocusAnimation(boolean hasFocus) {
+ if (mEmptyView.getVisibility() == View.VISIBLE) {
+ mEmptyViewFocusAnimationHolder.getFocusChangeAnimator(hasFocus).start();
+ } else {
+ mTaskStackHorizontalView.startRecentsRowFocusAnimation(hasFocus);
+ }
+ }
+
+ /**
* Hides the task stack and shows the empty view.
*/
public void showEmptyView() {
mEmptyView.setVisibility(View.VISIBLE);
- mEmptyView.bringToFront();
+ mTaskStackHorizontalView.setVisibility(View.GONE);
}
/**
* Shows the task stack and hides the empty view.
*/
public void hideEmptyView() {
- mEmptyView.setVisibility(View.INVISIBLE);
+ mEmptyView.setVisibility(View.GONE);
+ mTaskStackHorizontalView.setVisibility(View.VISIBLE);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 3343aec8891b..d60574891899 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -24,6 +24,7 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Display;
import android.view.KeyEvent;
+import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -31,6 +32,7 @@ import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.recents.tv.animations.DismissAnimationsHolder;
+import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
import com.android.systemui.recents.model.Task;
@@ -44,6 +46,7 @@ public class TaskCardView extends LinearLayout {
private ViewFocusAnimator mViewFocusAnimator;
private DismissAnimationsHolder mDismissAnimationsHolder;
+ private RecentsRowFocusAnimationHolder mRecentsRowFocusAnimationHolder;
public TaskCardView(Context context) {
this(context, null);
@@ -65,6 +68,8 @@ public class TaskCardView extends LinearLayout {
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
mDismissAnimationsHolder = new DismissAnimationsHolder(this);
+ View title = findViewById(R.id.card_info_field);
+ mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, title);
}
public void init(Task task) {
@@ -193,6 +198,10 @@ public class TaskCardView extends LinearLayout {
mDismissAnimationsHolder.startDismissAnimation(listener);
}
+ public RecentsRowFocusAnimationHolder getRecentsRowFocusAnimationHolder() {
+ return mRecentsRowFocusAnimationHolder;
+ }
+
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 5eb9fda98d93..603721a56eca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -15,7 +15,11 @@
*/
package com.android.systemui.recents.tv.views;
+import android.animation.Animator;
+import android.animation.AnimatorSet;
import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
import android.support.v17.leanback.widget.HorizontalGridView;
import android.util.AttributeSet;
import android.view.View;
@@ -36,10 +40,19 @@ import java.util.List;
* Horizontal Grid View Implementation to show the Task Stack for TV.
*/
public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
-
+ private static final int ANIMATION_DELAY_MS = 50;
+ private static final int MSG_START_RECENT_ROW_FOCUS_ANIMATION = 100;
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_START_RECENT_ROW_FOCUS_ANIMATION) {
+ startRecentsRowFocusAnimation(msg.arg1 == 1);
+ }
+ }
+ };
private TaskStack mStack;
- private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
private Task mFocusedTask;
+ private AnimatorSet mRecentsRowFocusAnimation;
public TaskStackHorizontalGridView(Context context) {
this(context, null);
@@ -62,10 +75,18 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
super.onDetachedFromWindow();
EventBus.getDefault().unregister(this);
}
+
/**
* Resets this view for reuse.
*/
public void reset() {
+ for (int i = 0; i < getChildCount(); i++) {
+ ((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder().reset();
+ }
+ if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
+ mRecentsRowFocusAnimation.cancel();
+ }
+ mHandler.removeCallbacksAndMessages(null);
requestLayout();
}
@@ -119,10 +140,8 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
* @return Child view for given task
*/
public TaskCardView getChildViewForTask(Task task) {
- List<TaskCardView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskCardView tv = taskViews.get(i);
+ for (int i = 0; i < getChildCount(); i++) {
+ TaskCardView tv = (TaskCardView) getChildAt(i);
if (tv.getTask() == task) {
return tv;
}
@@ -130,12 +149,36 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
return null;
}
- public List<TaskCardView> getTaskViews() {
- return mTaskViews;
+ /**
+ * Starts the focus change animation.
+ */
+ public void startRecentsRowFocusAnimation(final boolean hasFocus) {
+ if (getChildCount() == 0) {
+ // Animation request may happen before view is attached.
+ // Post again with small dealy so animation can be run again later.
+ if (getAdapter().getItemCount() > 0) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(
+ MSG_START_RECENT_ROW_FOCUS_ANIMATION, hasFocus ? 1 : 0),
+ ANIMATION_DELAY_MS);
+ }
+ return;
+ }
+ if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
+ mRecentsRowFocusAnimation.cancel();
+ }
+ Animator animator = ((TaskCardView) getChildAt(0)).getRecentsRowFocusAnimationHolder()
+ .getFocusChangeAnimator(hasFocus);
+ mRecentsRowFocusAnimation = new AnimatorSet();
+ AnimatorSet.Builder builder = mRecentsRowFocusAnimation.play(animator);
+ for (int i = 1; i < getChildCount(); i++) {
+ builder.with(((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder()
+ .getFocusChangeAnimator(hasFocus));
+ }
+ mRecentsRowFocusAnimation.start();
}
@Override
- public void onStackTaskAdded(TaskStack stack, Task newTask){
+ public void onStackTaskAdded(TaskStack stack, Task newTask) {
getAdapter().notifyItemInserted(stack.getStackTasks().indexOf(newTask));
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index e0d048660b96..21a43d5c3e52 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -74,6 +74,8 @@ import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecC
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.FlingAnimationUtils;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -83,6 +85,8 @@ import java.util.List;
*/
public class RecentsView extends FrameLayout {
+ private static final String TAG = "RecentsView";
+
private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
@@ -367,8 +371,10 @@ public class RecentsView extends FrameLayout {
int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom;
int childWidth = mEmptyView.getMeasuredWidth();
int childHeight = mEmptyView.getMeasuredHeight();
- int childLeft = left + Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
- int childTop = top + Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
+ int childLeft = left + mSystemInsets.left +
+ Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
+ int childTop = top + mSystemInsets.top +
+ Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
@@ -756,4 +762,22 @@ public class RecentsView extends FrameLayout {
top + mStackActionButton.getMeasuredHeight());
return actionButtonRect;
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+ String id = Integer.toHexString(System.identityHashCode(this));
+
+ writer.print(prefix); writer.print(TAG);
+ writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N");
+ writer.print(" insets="); writer.print(Utilities.dumpRect(mSystemInsets));
+ writer.print(" [0x"); writer.print(id); writer.print("]");
+ writer.println();
+
+ if (mStack != null) {
+ mStack.dump(innerPrefix, writer);
+ }
+ if (mTaskStackView != null) {
+ mTaskStackView.dump(innerPrefix, writer);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index 1c433d8eb31c..fe91f421c202 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -456,7 +456,8 @@ public class TaskStackAnimationHelper {
TaskStack stack = mStackView.getStack();
final float curScroll = stackScroller.getStackScroll();
- final float newScroll = stackLayout.getStackScrollForTask(newFocusedTask);
+ final float newScroll = stackScroller.getBoundedStackScroll(
+ stackLayout.getStackScrollForTask(newFocusedTask));
boolean willScrollToFront = newScroll > curScroll;
boolean willScroll = Float.compare(newScroll, curScroll) != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 9eab0f60584f..b75a91e8c42b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -29,6 +29,7 @@ import android.view.ViewDebug;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
@@ -38,6 +39,7 @@ import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -108,6 +110,8 @@ class Range {
*/
public class TaskStackLayoutAlgorithm {
+ private static final String TAG = "TaskStackLayoutAlgorithm";
+
// The distribution of view bounds alpha
// XXX: This is a hack because you can currently set the max alpha to be > 1f
public static final float OUTLINE_ALPHA_MIN_VALUE = 0f;
@@ -530,8 +534,12 @@ public class TaskStackLayoutAlgorithm {
? stack.indexOfStackTask(launchTask)
: mNumStackTasks - 1;
if (getInitialFocusState() == STATE_FOCUSED) {
+ int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
+ float maxBottomNormX = getNormalizedXFromFocusedY(maxBottomOffset, FROM_BOTTOM);
+ mFocusedRange.offset(0f);
mMinScrollP = 0;
- mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
+ mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
+ Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX)));
if (launchState.launchedFromHome) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
} else {
@@ -555,7 +563,10 @@ public class TaskStackLayoutAlgorithm {
Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
boolean scrollToFront = launchState.launchedFromHome ||
launchState.launchedViaDockGesture;
- if (scrollToFront) {
+ if (launchState.launchedWithAltTab) {
+ mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
+ mInitialNormX = null;
+ } else if (scrollToFront) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
mInitialNormX = null;
} else {
@@ -652,8 +663,9 @@ public class TaskStackLayoutAlgorithm {
* Returns the default focus state.
*/
public int getInitialFocusState() {
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- if (debugFlags.isPagingEnabled()) {
+ if (debugFlags.isPagingEnabled() || launchState.launchedWithAltTab) {
return STATE_FOCUSED;
} else {
return STATE_UNFOCUSED;
@@ -675,7 +687,6 @@ public class TaskStackLayoutAlgorithm {
}
/**
- *
* Returns the current stack state.
*/
public StackState getStackState() {
@@ -1027,6 +1038,18 @@ public class TaskStackLayoutAlgorithm {
}
/**
+ * Returns the normalized x on the focused curve given an absolute Y position (relative to the
+ * stack height).
+ */
+ private float getNormalizedXFromFocusedY(float y, @AnchorSide int fromSide) {
+ float offset = (fromSide == FROM_TOP)
+ ? mStackRect.height() - y
+ : y;
+ float offsetPct = offset / mStackRect.height();
+ return mFocusedCurveInterpolator.getX(offsetPct);
+ }
+
+ /**
* Creates a new path for the focused curve.
*/
private Path constructFocusedCurve() {
@@ -1036,10 +1059,13 @@ public class TaskStackLayoutAlgorithm {
float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
float bottomPeekHeightPct = (float) (mStackBottomOffset + mFocusedBottomPeekHeight) /
mStackRect.height();
+ float minBottomPeekHeightPct = (float) (mFocusedTopPeekHeight + mTaskRect.height() -
+ mMinMargin) / mStackRect.height();
Path p = new Path();
p.moveTo(0f, 1f);
p.lineTo(0.5f, 1f - topPeekHeightPct);
- p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), bottomPeekHeightPct);
+ p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), Math.max(1f - minBottomPeekHeightPct,
+ bottomPeekHeightPct));
p.lineTo(1f, 0f);
return p;
}
@@ -1133,4 +1159,44 @@ public class TaskStackLayoutAlgorithm {
mBackOfStackTransform.visible = true;
mFrontOfStackTransform.visible = true;
}
-}
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+
+ writer.print(prefix); writer.print(TAG);
+ writer.write(" numStackTasks="); writer.write(mNumStackTasks);
+ writer.println();
+
+ writer.print(innerPrefix);
+ writer.print("insets="); writer.print(Utilities.dumpRect(mSystemInsets));
+ writer.print(" stack="); writer.print(Utilities.dumpRect(mStackRect));
+ writer.print(" task="); writer.print(Utilities.dumpRect(mTaskRect));
+ writer.print(" freeform="); writer.print(Utilities.dumpRect(mFreeformRect));
+ writer.print(" actionButton="); writer.print(Utilities.dumpRect(mStackActionButtonRect));
+ writer.println();
+
+ writer.print(innerPrefix);
+ writer.print("minScroll="); writer.print(mMinScrollP);
+ writer.print(" maxScroll="); writer.print(mMaxScrollP);
+ writer.print(" initialScroll="); writer.print(mInitialScrollP);
+ writer.println();
+
+ writer.print(innerPrefix);
+ writer.print("focusState="); writer.print(mFocusState);
+ writer.println();
+
+ if (mTaskIndexOverrideMap.size() > 0) {
+ for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
+ int taskId = mTaskIndexOverrideMap.keyAt(i);
+ float x = mTaskIndexMap.get(taskId);
+ float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
+
+ writer.print(innerPrefix);
+ writer.print("taskId= "); writer.print(taskId);
+ writer.print(" x= "); writer.print(x);
+ writer.print(" overrideX= "); writer.print(overrideX);
+ writer.println();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 5416a4897666..13c8403ab0ab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -90,6 +90,7 @@ import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -102,6 +103,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks,
ViewPool.ViewPoolConsumer<TaskView, Task> {
+ private static final String TAG = "TaskStackView";
+
private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super";
private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE =
"saved_instance_state_layout_focused_state";
@@ -2067,4 +2070,37 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mScreenPinningEnabled = ssp.getSystemSetting(getContext(),
Settings.System.LOCK_TO_APP_ENABLED) != 0;
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+ String id = Integer.toHexString(System.identityHashCode(this));
+
+ writer.print(prefix); writer.print(TAG);
+ writer.print(" hasDefRelayout=");
+ writer.print(mDeferredTaskViewLayoutAnimation != null ? "Y" : "N");
+ writer.print(" clipDirty="); writer.print(mTaskViewsClipDirty ? "Y" : "N");
+ writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N");
+ writer.print(" initialState="); writer.print(mInitialState);
+ writer.print(" inMeasureLayout="); writer.print(mInMeasureLayout ? "Y" : "N");
+ writer.print(" enterAnimCompleted="); writer.print(mEnterAnimationComplete ? "Y" : "N");
+ writer.print(" touchExplorationOn="); writer.print(mTouchExplorationEnabled ? "Y" : "N");
+ writer.print(" screenPinningOn="); writer.print(mScreenPinningEnabled ? "Y" : "N");
+ writer.print(" numIgnoreTasks="); writer.print(mIgnoreTasks.size());
+ writer.print(" numViewPool="); writer.print(mViewPool.getViews().size());
+ writer.print(" stableStackBounds="); writer.print(Utilities.dumpRect(mStableStackBounds));
+ writer.print(" stackBounds="); writer.print(Utilities.dumpRect(mStackBounds));
+ writer.print(" stableWindow="); writer.print(Utilities.dumpRect(mStableWindowRect));
+ writer.print(" window="); writer.print(Utilities.dumpRect(mWindowRect));
+ writer.print(" [0x"); writer.print(id); writer.print("]");
+ writer.println();
+
+ if (mFocusedTask != null) {
+ writer.print(innerPrefix);
+ writer.print("Focused task: ");
+ mFocusedTask.dump(innerPrefix, writer);
+ }
+
+ mLayoutAlgorithm.dump(innerPrefix, writer);
+ mStackScroller.dump(innerPrefix, writer);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 583fb88e4069..19b3c943ae65 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -30,6 +30,8 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.misc.Utilities;
+import java.io.PrintWriter;
+
/* The scrolling logic for a TaskStackView */
public class TaskStackViewScroller {
@@ -246,4 +248,10 @@ public class TaskStackViewScroller {
mScroller.abortAnimation();
}
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ writer.print(prefix); writer.print(TAG);
+ writer.print(" stackScroll:"); writer.print(mStackScrollP);
+ writer.println();
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index a2f61c267f03..570ff8a07fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -459,7 +459,7 @@ public class TaskViewHeader extends FrameLayout
if (!mTitleView.getText().toString().equals(t.title)) {
mTitleView.setText(t.title);
}
- mTitleView.setContentDescription(t.contentDescription);
+ mTitleView.setContentDescription(t.titleDescription);
mTitleView.setTextColor(t.useLightOnPrimaryColor ?
mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
if (!t.isDockable && ssp.hasDockedTask()) {
@@ -501,6 +501,7 @@ public class TaskViewHeader extends FrameLayout
// In accessibility, a single click on the focused app info button will show it
if (touchExplorationEnabled) {
+ mIconView.setContentDescription(t.appInfoDescription);
mIconView.setOnClickListener(this);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index e8cf1261a63b..d294c80bdf51 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -34,8 +34,6 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
* Controls the docked stack divider.
*/
public class Divider extends SystemUI {
- private static final String TAG = "Divider";
- private int mDividerWindowWidth;
private DividerWindowManager mWindowManager;
private DividerView mView;
private DockDividerVisibilityListener mDockDividerVisibilityListener;
@@ -46,8 +44,6 @@ public class Divider extends SystemUI {
@Override
public void start() {
mWindowManager = new DividerWindowManager(mContext);
- mDividerWindowWidth = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_thickness);
update(mContext.getResources().getConfiguration());
putComponent(Divider.class, this);
mDockDividerVisibilityListener = new DockDividerVisibilityListener();
@@ -70,9 +66,11 @@ public class Divider extends SystemUI {
mView = (DividerView)
LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
+ final int size = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_thickness);
final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
- final int width = landscape ? mDividerWindowWidth : MATCH_PARENT;
- final int height = landscape ? MATCH_PARENT : mDividerWindowWidth;
+ final int width = landscape ? size : MATCH_PARENT;
+ final int height = landscape ? MATCH_PARENT : size;
mWindowManager.add(mView, width, height);
mView.setWindowManager(mWindowManager);
}
@@ -97,6 +95,9 @@ public class Divider extends SystemUI {
if (mVisible != visible) {
mVisible = visible;
mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+
+ // Update state because animations won't finish.
+ mView.setMinimizedDockStack(mMinimized);
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 7a933cd6576a..3005535535cc 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -134,6 +134,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private ValueAnimator mCurrentAnimator;
private boolean mEntranceAnimationRunning;
private GestureDetector mGestureDetector;
+ private boolean mDockedStackMinimized;
private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
@Override
@@ -239,16 +240,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
protected void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
- getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-
- @Override
- public void onGlobalLayout() {
- getViewTreeObserver().removeOnGlobalLayoutListener(this);
- mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
- mHandle.getLeft() + mHandle.getWidth(),
- mHandle.getTop() + mHandle.getHeight()));
- }
- });
}
@Override
@@ -273,6 +264,15 @@ public class DividerView extends FrameLayout implements OnTouchListener,
return super.onApplyWindowInsets(insets);
}
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed) {
+ mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
+ mHandle.getRight(), mHandle.getBottom()));
+ }
+ }
+
public void setWindowManager(DividerWindowManager windowManager) {
mWindowManager = windowManager;
}
@@ -538,6 +538,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
: mBackground.getWidth());
mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
}
+ mDockedStackMinimized = minimized;
}
public void setMinimizedDockStack(boolean minimized, long animDuration) {
@@ -566,6 +567,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setDuration(animDuration)
.start();
+ mDockedStackMinimized = minimized;
}
private void resetBackground() {
@@ -883,7 +885,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
public final void onBusEvent(UndockingTaskEvent undockingTaskEvent) {
int dockSide = mWindowManagerProxy.getDockSide();
- if (dockSide != WindowManager.DOCKED_INVALID) {
+ if (dockSide != WindowManager.DOCKED_INVALID && !mDockedStackMinimized) {
startDragging(false /* animate */, false /* touching */);
SnapTarget target = dockSideTopLeft(dockSide)
? mSnapAlgorithm.getDismissEndTarget()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 4ed64260dc7f..1b2393afcccf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -91,6 +91,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -100,6 +101,7 @@ import com.android.systemui.SystemUI;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationGuts.OnGutsClosedListener;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -107,7 +109,6 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.GearDisplayedListener;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import java.util.ArrayList;
@@ -115,12 +116,12 @@ import java.util.List;
import java.util.Locale;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-import static com.android.keyguard.KeyguardHostView.OnDismissAction;
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
- ExpandableNotificationRow.OnExpandClickListener, GearDisplayedListener {
+ ExpandableNotificationRow.OnExpandClickListener,
+ OnGutsClosedListener {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
@@ -242,7 +243,6 @@ public abstract class BaseStatusBar extends SystemUI implements
// which notification is currently being longpress-examined by the user
private NotificationGuts mNotificationGutsExposed;
- private ExpandableNotificationRow mNotificationGearDisplayed;
private KeyboardShortcuts mKeyboardShortcuts;
@@ -287,9 +287,10 @@ public abstract class BaseStatusBar extends SystemUI implements
private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
- // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
- // so we just dump our cache ...
+ // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
+ // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
mUsersAllowingPrivateNotifications.clear();
+ mUsersAllowingNotifications.clear();
// ... and refresh all the notifications
updateNotifications();
}
@@ -1012,6 +1013,7 @@ public abstract class BaseStatusBar extends SystemUI implements
PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
row.setTag(sbn.getPackageName());
final NotificationGuts guts = row.getGuts();
+ guts.setClosedListener(this);
final String pkg = sbn.getPackageName();
String appname = pkg;
Drawable pkgicon = null;
@@ -1039,6 +1041,7 @@ public abstract class BaseStatusBar extends SystemUI implements
settingsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
+ guts.resetFalsingCheck();
startAppNotificationSettingsActivity(pkg, appUidF);
}
});
@@ -1049,26 +1052,41 @@ public abstract class BaseStatusBar extends SystemUI implements
row.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- guts.saveImportance(sbn);
-
- int[] rowLocation = new int[2];
- int[] doneLocation = new int[2];
- row.getLocationOnScreen(rowLocation);
- v.getLocationOnScreen(doneLocation);
-
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = doneLocation[0] - rowLocation[0] + centerX;
- final int y = doneLocation[1] - rowLocation[1] + centerY;
- dismissPopups(x, y);
+ // If the user has security enabled, show challenge if the setting is changed.
+ if (guts.hasImportanceChanged() && isLockscreenPublicMode() &&
+ (mState == StatusBarState.KEYGUARD
+ || mState == StatusBarState.SHADE_LOCKED)) {
+ OnDismissAction dismissAction = new OnDismissAction() {
+ @Override
+ public boolean onDismiss() {
+ saveImportanceCloseControls(sbn, row, guts, v);
+ return true;
+ }
+ };
+ onLockedNotificationImportanceChange(dismissAction);
+ } else {
+ saveImportanceCloseControls(sbn, row, guts, v);
+ }
}
});
-
guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
}
- protected GearDisplayedListener getGearDisplayedListener() {
- return this;
+ private void saveImportanceCloseControls(StatusBarNotification sbn,
+ ExpandableNotificationRow row, NotificationGuts guts, View done) {
+ guts.resetFalsingCheck();
+ guts.saveImportance(sbn);
+
+ int[] rowLocation = new int[2];
+ int[] doneLocation = new int[2];
+ row.getLocationOnScreen(rowLocation);
+ done.getLocationOnScreen(doneLocation);
+
+ final int centerX = done.getWidth() / 2;
+ final int centerY = done.getHeight() / 2;
+ final int x = doneLocation[0] - rowLocation[0] + centerX;
+ final int y = doneLocation[1] - rowLocation[1] + centerY;
+ dismissPopups(x, y);
}
protected SwipeHelper.LongPressListener getNotificationLongClicker() {
@@ -1106,7 +1124,8 @@ public abstract class BaseStatusBar extends SystemUI implements
// Post to ensure the the guts are properly laid out.
guts.post(new Runnable() {
public void run() {
- dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */);
+ dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
+ false /* animate */);
guts.setVisibility(View.VISIBLE);
final double horz = Math.max(guts.getWidth() - x, x);
final double vert = Math.max(guts.getHeight() - y, y);
@@ -1124,7 +1143,8 @@ public abstract class BaseStatusBar extends SystemUI implements
}
});
a.start();
- guts.setExposed(true);
+ guts.setExposed(true /* exposed */,
+ mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
row.closeRemoteInput();
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
mNotificationGutsExposed = guts;
@@ -1135,56 +1155,37 @@ public abstract class BaseStatusBar extends SystemUI implements
};
}
- @Override
- public void onGearDisplayed(ExpandableNotificationRow row) {
- MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
- row.getStatusBarNotification().getPackageName());
- mNotificationGearDisplayed = row;
+ /**
+ * Returns the exposed NotificationGuts or null if none are exposed.
+ */
+ public NotificationGuts getExposedGuts() {
+ return mNotificationGutsExposed;
}
public void dismissPopups() {
- dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */);
+ dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
}
private void dismissPopups(int x, int y) {
- dismissPopups(x, y, true /* resetGear */);
+ dismissPopups(x, y, true /* resetGear */, false /* animate */);
}
- public void dismissPopups(int x, int y, boolean resetGear) {
+ public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
if (mNotificationGutsExposed != null) {
- final NotificationGuts v = mNotificationGutsExposed;
- mNotificationGutsExposed = null;
-
- if (v.getWindowToken() == null) return;
- if (x == -1 || y == -1) {
- x = (v.getLeft() + v.getRight()) / 2;
- y = (v.getTop() + v.getHeight() / 2);
- }
- final double horz = Math.max(v.getWidth() - x, x);
- final double vert = Math.max(v.getHeight() - y, y);
- final float r = (float) Math.hypot(horz, vert);
- final Animator a = ViewAnimationUtils.createCircularReveal(v,
- x, y, r, 0);
- a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
- a.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- v.setVisibility(View.GONE);
- }
- });
- a.start();
- v.setExposed(false);
- mStackScroller.onHeightChanged(null, true /* needsAnimation */);
+ mNotificationGutsExposed.closeControls(x, y, true /* notify */);
}
- if (resetGear && mNotificationGearDisplayed != null) {
- mNotificationGearDisplayed.resetTranslation();
- mNotificationGearDisplayed = null;
+ if (resetGear) {
+ mStackScroller.resetExposedGearView(animate, true /* force */);
}
}
@Override
+ public void onGutsClosed(NotificationGuts guts) {
+ mStackScroller.onHeightChanged(null, true /* needsAnimation */);
+ mNotificationGutsExposed = null;
+ }
+
+ @Override
public void showRecentApps(boolean triggeredFromAltTab) {
int msg = MSG_SHOW_RECENT_APPS;
mHandler.removeMessages(msg);
@@ -1456,6 +1457,8 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
+ protected void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {}
+
protected void onLockedRemoteInput(ExpandableNotificationRow row, View clickedView) {}
@Override
@@ -1843,11 +1846,12 @@ public abstract class BaseStatusBar extends SystemUI implements
.getIdentifier();
if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
&& mKeyguardManager.isDeviceLocked(userId)) {
- // Show work challenge, do not run pendingintent and
- // remove notification
- startWorkChallenge(userId, intent.getIntentSender(),
- notificationKey);
- return;
+ if (startWorkChallengeIfNecessary(userId,
+ intent.getIntentSender(), notificationKey)) {
+ // Show work challenge, do not run pendingintent and
+ // remove notification
+ return;
+ }
}
}
try {
@@ -1885,21 +1889,25 @@ public abstract class BaseStatusBar extends SystemUI implements
}, afterKeyguardGone);
}
- public void startWorkChallenge(int userId, IntentSender intendSender,
+ public boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
String notificationKey) {
+ final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
+ null, userId);
+ if (newIntent == null) {
+ return false;
+ }
final Intent callBackIntent = new Intent(
WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
callBackIntent.setPackage(mContext.getPackageName());
- final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
- null, userId);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_CLEAR_TASK);
newIntent.putExtra(Intent.EXTRA_INTENT, PendingIntent
.getBroadcast(mContext, 0, callBackIntent, 0).getIntentSender());
mContext.startActivity(newIntent);
+ return true;
}
public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 7f87c3c687d8..2dabf5d32016 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -170,22 +170,22 @@ public class DragDownHelper implements Gefingerpoken {
: RUBBERBAND_FACTOR_STATIC;
float rubberband = heightDelta * rubberbandFactor;
if (expandable
- && (rubberband + child.getMinExpandHeight()) > child.getMaxContentHeight()) {
+ && (rubberband + child.getCollapsedHeight()) > child.getMaxContentHeight()) {
float overshoot =
- (rubberband + child.getMinExpandHeight()) - child.getMaxContentHeight();
+ (rubberband + child.getCollapsedHeight()) - child.getMaxContentHeight();
overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
rubberband -= overshoot;
}
- child.setActualHeight((int) (child.getMinExpandHeight() + rubberband));
+ child.setActualHeight((int) (child.getCollapsedHeight() + rubberband));
}
private void cancelExpansion(final ExpandableView child) {
- if (child.getActualHeight() == child.getMinExpandHeight()) {
+ if (child.getActualHeight() == child.getCollapsedHeight()) {
mCallback.setUserLockedChild(child, false);
return;
}
ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
- child.getActualHeight(), child.getMinExpandHeight());
+ child.getActualHeight(), child.getCollapsedHeight());
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f9edeb312644..7ca7d12c590a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -470,7 +470,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
if(mExpandedWhenPinned) {
return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
} else if (atLeastMinHeight) {
- return Math.max(getMinHeight(), mHeadsUpHeight);
+ return Math.max(getCollapsedHeight(), mHeadsUpHeight);
} else {
return mHeadsUpHeight;
}
@@ -1040,12 +1040,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
} else if (isExpanded()) {
return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
} else {
- return Math.max(getMinHeight(), mHeadsUpHeight);
+ return Math.max(getCollapsedHeight(), mHeadsUpHeight);
}
} else if (isExpanded()) {
return getMaxExpandHeight();
} else {
- return getMinHeight();
+ return getCollapsedHeight();
}
}
@@ -1301,9 +1301,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
@Override
- public int getMinExpandHeight() {
+ public int getCollapsedHeight() {
if (mIsSummaryWithChildren && !mShowingPublic) {
- return mChildrenContainer.getMinExpandHeight();
+ return mChildrenContainer.getCollapsedHeight();
}
return getMinHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 91418ad312bf..6dcd61f259f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -153,11 +153,11 @@ public abstract class ExpandableView extends FrameLayout {
}
/**
- * @return The minimum height this child chan be expanded to. Note that this might be different
- * than {@link #getMinHeight()} because some elements can't be collapsed by an expand gesture
- * to it's absolute minimal height
+ * @return The collapsed height of this view. Note that this might be different
+ * than {@link #getMinHeight()} because some elements like groups may have different sizes when
+ * they are system expanded.
*/
- public int getMinExpandHeight() {
+ public int getCollapsedHeight() {
return getHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 2b365dc743e9..977a77d59559 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -21,6 +21,9 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
@@ -37,6 +40,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -52,175 +56,191 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
/**
* Contains functionality for handling keyboard shortcuts.
*/
-public class KeyboardShortcuts {
+public final class KeyboardShortcuts {
private static final String TAG = KeyboardShortcuts.class.getSimpleName();
- private static final SparseArray<String> SPECIAL_CHARACTER_NAMES = new SparseArray<>();
- private static final SparseArray<String> MODIFIER_NAMES = new SparseArray<>();
+ private final SparseArray<String> mSpecialCharacterNames = new SparseArray<>();
+ private final SparseArray<String> mModifierNames = new SparseArray<>();
+ private final SparseArray<Drawable> mSpecialCharacterDrawables = new SparseArray<>();
+ private final SparseArray<Drawable> mModifierDrawables = new SparseArray<>();
- private static void loadSpecialCharacterNames(Context context) {
- SPECIAL_CHARACTER_NAMES.put(
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final Context mContext;
+ private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dismissKeyboardShortcutsDialog();
+ }
+ };
+
+ private Dialog mKeyboardShortcutsDialog;
+ private KeyCharacterMap mKeyCharacterMap;
+
+ public KeyboardShortcuts(Context context) {
+ this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
+ loadResources(context);
+ }
+
+ private void loadResources(Context context) {
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_BACK, context.getString(R.string.keyboard_key_back));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_DPAD_UP, context.getString(R.string.keyboard_key_dpad_up));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_DPAD_DOWN, context.getString(R.string.keyboard_key_dpad_down));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_DPAD_LEFT, context.getString(R.string.keyboard_key_dpad_left));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_DPAD_RIGHT, context.getString(R.string.keyboard_key_dpad_right));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_DPAD_CENTER, context.getString(R.string.keyboard_key_dpad_center));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_PERIOD, ".");
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_PERIOD, ".");
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_TAB, context.getString(R.string.keyboard_key_tab));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_SPACE, context.getString(R.string.keyboard_key_space));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_ENTER, context.getString(R.string.keyboard_key_enter));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_DEL, context.getString(R.string.keyboard_key_backspace));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
context.getString(R.string.keyboard_key_media_play_pause));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_MEDIA_STOP, context.getString(R.string.keyboard_key_media_stop));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_MEDIA_NEXT, context.getString(R.string.keyboard_key_media_next));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS,
context.getString(R.string.keyboard_key_media_previous));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_REWIND,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_REWIND,
context.getString(R.string.keyboard_key_media_rewind));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
context.getString(R.string.keyboard_key_media_fast_forward));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_PAGE_UP, context.getString(R.string.keyboard_key_page_up));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_PAGE_DOWN, context.getString(R.string.keyboard_key_page_down));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_A,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_A,
context.getString(R.string.keyboard_key_button_template, "A"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_B,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_B,
context.getString(R.string.keyboard_key_button_template, "B"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_C,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_C,
context.getString(R.string.keyboard_key_button_template, "C"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_X,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_X,
context.getString(R.string.keyboard_key_button_template, "X"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Y,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Y,
context.getString(R.string.keyboard_key_button_template, "Y"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Z,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Z,
context.getString(R.string.keyboard_key_button_template, "Z"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L1,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L1,
context.getString(R.string.keyboard_key_button_template, "L1"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R1,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R1,
context.getString(R.string.keyboard_key_button_template, "R1"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L2,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L2,
context.getString(R.string.keyboard_key_button_template, "L2"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R2,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R2,
context.getString(R.string.keyboard_key_button_template, "R2"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_START,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_START,
context.getString(R.string.keyboard_key_button_template, "Start"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_SELECT,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_SELECT,
context.getString(R.string.keyboard_key_button_template, "Select"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_MODE,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_MODE,
context.getString(R.string.keyboard_key_button_template, "Mode"));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_FORWARD_DEL, context.getString(R.string.keyboard_key_forward_del));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ESCAPE, "Esc");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SYSRQ, "SysRq");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BREAK, "Break");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock");
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_ESCAPE, "Esc");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_SYSRQ, "SysRq");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BREAK, "Break");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock");
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_MOVE_HOME, context.getString(R.string.keyboard_key_move_home));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_MOVE_END, context.getString(R.string.keyboard_key_move_end));
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_INSERT, context.getString(R.string.keyboard_key_insert));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F1, "F1");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F2, "F2");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F3, "F3");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F4, "F4");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F5, "F5");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F6, "F6");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F7, "F7");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F8, "F8");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F9, "F9");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F10, "F10");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F11, "F11");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F12, "F12");
- SPECIAL_CHARACTER_NAMES.put(
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F1, "F1");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F2, "F2");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F3, "F3");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F4, "F4");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F5, "F5");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F6, "F6");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F7, "F7");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F8, "F8");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F9, "F9");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F10, "F10");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F11, "F11");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F12, "F12");
+ mSpecialCharacterNames.put(
KeyEvent.KEYCODE_NUM_LOCK, context.getString(R.string.keyboard_key_num_lock));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_0,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_0,
context.getString(R.string.keyboard_key_numpad_template, "0"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_1,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_1,
context.getString(R.string.keyboard_key_numpad_template, "1"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_2,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_2,
context.getString(R.string.keyboard_key_numpad_template, "2"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_3,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_3,
context.getString(R.string.keyboard_key_numpad_template, "3"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_4,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_4,
context.getString(R.string.keyboard_key_numpad_template, "4"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_5,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_5,
context.getString(R.string.keyboard_key_numpad_template, "5"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_6,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_6,
context.getString(R.string.keyboard_key_numpad_template, "6"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_7,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_7,
context.getString(R.string.keyboard_key_numpad_template, "7"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_8,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_8,
context.getString(R.string.keyboard_key_numpad_template, "8"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_9,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_9,
context.getString(R.string.keyboard_key_numpad_template, "9"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE,
context.getString(R.string.keyboard_key_numpad_template, "/"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY,
context.getString(R.string.keyboard_key_numpad_template, "*"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT,
context.getString(R.string.keyboard_key_numpad_template, "-"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ADD,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ADD,
context.getString(R.string.keyboard_key_numpad_template, "+"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DOT,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DOT,
context.getString(R.string.keyboard_key_numpad_template, "."));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_COMMA,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_COMMA,
context.getString(R.string.keyboard_key_numpad_template, ","));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ENTER,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ENTER,
context.getString(R.string.keyboard_key_numpad_template,
context.getString(R.string.keyboard_key_enter)));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_EQUALS,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_EQUALS,
context.getString(R.string.keyboard_key_numpad_template, "="));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN,
context.getString(R.string.keyboard_key_numpad_template, "("));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN,
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN,
context.getString(R.string.keyboard_key_numpad_template, ")"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_EISU, "英数");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_HENKAN, "変換");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_EISU, "英数");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_HENKAN, "変換");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
- MODIFIER_NAMES.put(KeyEvent.META_META_ON, "Meta");
- MODIFIER_NAMES.put(KeyEvent.META_CTRL_ON, "Ctrl");
- MODIFIER_NAMES.put(KeyEvent.META_ALT_ON, "Alt");
- MODIFIER_NAMES.put(KeyEvent.META_SHIFT_ON, "Shift");
- MODIFIER_NAMES.put(KeyEvent.META_SYM_ON, "Sym");
- MODIFIER_NAMES.put(KeyEvent.META_FUNCTION_ON, "Fn");
- }
+ mModifierNames.put(KeyEvent.META_META_ON, "Meta");
+ mModifierNames.put(KeyEvent.META_CTRL_ON, "Ctrl");
+ mModifierNames.put(KeyEvent.META_ALT_ON, "Alt");
+ mModifierNames.put(KeyEvent.META_SHIFT_ON, "Shift");
+ mModifierNames.put(KeyEvent.META_SYM_ON, "Sym");
+ mModifierNames.put(KeyEvent.META_FUNCTION_ON, "Fn");
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final Context mContext;
- private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dismissKeyboardShortcutsDialog();
- }
- };
-
- private Dialog mKeyboardShortcutsDialog;
- private KeyCharacterMap mKeyCharacterMap;
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DEL, context.getDrawable(R.drawable.ic_ksh_key_backspace));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_ENTER, context.getDrawable(R.drawable.ic_ksh_key_enter));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_UP, context.getDrawable(R.drawable.ic_ksh_key_up));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_RIGHT, context.getDrawable(R.drawable.ic_ksh_key_right));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_DOWN, context.getDrawable(R.drawable.ic_ksh_key_down));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_LEFT, context.getDrawable(R.drawable.ic_ksh_key_left));
- public KeyboardShortcuts(Context context) {
- this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
- if (SPECIAL_CHARACTER_NAMES.size() == 0) {
- loadSpecialCharacterNames(context);
- }
+ mModifierDrawables.put(
+ KeyEvent.META_META_ON, context.getDrawable(R.drawable.ic_ksh_key_meta));
}
public void toggleKeyboardShortcuts(int deviceId) {
@@ -343,6 +363,8 @@ public class KeyboardShortcuts {
List<KeyboardShortcutGroup> keyboardShortcutGroups) {
LayoutInflater inflater = LayoutInflater.from(mContext);
final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
+ // Needed to be able to scale the image items to the same height as the text items.
+ final int shortcutTextItemHeight = getShortcutTextItemHeight(inflater);
for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
TextView categoryTitle = (TextView) inflater.inflate(
@@ -364,7 +386,7 @@ public class KeyboardShortcuts {
Log.w(TAG, "Keyboard Shortcut contains key not on device, skipping.");
continue;
}
- List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
+ List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
if (shortcutKeys == null) {
// Ignore shortcuts we can't display keys for.
Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping.");
@@ -380,11 +402,26 @@ public class KeyboardShortcuts {
.findViewById(R.id.keyboard_shortcuts_item_container);
final int shortcutKeysSize = shortcutKeys.size();
for (int k = 0; k < shortcutKeysSize; k++) {
- String shortcutKey = shortcutKeys.get(k);
- TextView shortcutKeyView = (TextView) inflater.inflate(
- R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false);
- shortcutKeyView.setText(shortcutKey);
- shortcutItemsContainer.addView(shortcutKeyView);
+ StringOrDrawable shortcutRepresentation = shortcutKeys.get(k);
+ if (shortcutRepresentation.drawable != null) {
+ ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
+ false);
+ Bitmap bitmap = Bitmap.createBitmap(shortcutTextItemHeight,
+ shortcutTextItemHeight, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
+ canvas.getHeight());
+ shortcutRepresentation.drawable.draw(canvas);
+ shortcutKeyIconView.setImageBitmap(bitmap);
+ shortcutItemsContainer.addView(shortcutKeyIconView);
+ } else if (shortcutRepresentation.string != null) {
+ TextView shortcutKeyTextView = (TextView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
+ false);
+ shortcutKeyTextView.setText(shortcutRepresentation.string);
+ shortcutItemsContainer.addView(shortcutKeyTextView);
+ }
}
shortcutContainer.addView(shortcutView);
}
@@ -398,16 +435,29 @@ public class KeyboardShortcuts {
}
}
- private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
- List<String> shortcutKeys = getHumanReadableModifiers(info);
+ private int getShortcutTextItemHeight(LayoutInflater inflater) {
+ TextView shortcutKeyTextView = (TextView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_view, null, false);
+ shortcutKeyTextView.measure(
+ View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ return shortcutKeyTextView.getMeasuredHeight()
+ - shortcutKeyTextView.getPaddingTop()
+ - shortcutKeyTextView.getPaddingBottom();
+ }
+
+ private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+ List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
if (shortcutKeys == null) {
return null;
}
- String displayLabelString;
+ String displayLabelString = null;
+ Drawable displayLabelDrawable = null;
if (info.getBaseCharacter() > Character.MIN_VALUE) {
displayLabelString = String.valueOf(info.getBaseCharacter());
- } else if (SPECIAL_CHARACTER_NAMES.get(info.getKeycode()) != null) {
- displayLabelString = SPECIAL_CHARACTER_NAMES.get(info.getKeycode());
+ } else if (mSpecialCharacterDrawables.get(info.getKeycode()) != null) {
+ displayLabelDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+ } else if (mSpecialCharacterNames.get(info.getKeycode()) != null) {
+ displayLabelString = mSpecialCharacterNames.get(info.getKeycode());
} else {
// Special case for shortcuts with no base key or keycode.
if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) {
@@ -422,20 +472,31 @@ public class KeyboardShortcuts {
return null;
}
}
- shortcutKeys.add(displayLabelString.toUpperCase());
+
+ if (displayLabelDrawable != null) {
+ shortcutKeys.add(new StringOrDrawable(displayLabelDrawable));
+ } else if (displayLabelString != null) {
+ shortcutKeys.add(new StringOrDrawable(displayLabelString.toUpperCase()));
+ }
return shortcutKeys;
}
- private List<String> getHumanReadableModifiers(KeyboardShortcutInfo info) {
- final List<String> shortcutKeys = new ArrayList<>();
+ private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) {
+ final List<StringOrDrawable> shortcutKeys = new ArrayList<>();
int modifiers = info.getModifiers();
if (modifiers == 0) {
return shortcutKeys;
}
- for(int i = 0; i < MODIFIER_NAMES.size(); ++i) {
- final int supportedModifier = MODIFIER_NAMES.keyAt(i);
+ for(int i = 0; i < mModifierNames.size(); ++i) {
+ final int supportedModifier = mModifierNames.keyAt(i);
if ((modifiers & supportedModifier) != 0) {
- shortcutKeys.add(MODIFIER_NAMES.get(supportedModifier).toUpperCase());
+ if (mModifierDrawables.get(supportedModifier) != null) {
+ shortcutKeys.add(new StringOrDrawable(
+ mModifierDrawables.get(supportedModifier)));
+ } else {
+ shortcutKeys.add(new StringOrDrawable(
+ mModifierNames.get(supportedModifier).toUpperCase()));
+ }
modifiers &= ~supportedModifier;
}
}
@@ -445,4 +506,17 @@ public class KeyboardShortcuts {
}
return shortcutKeys;
}
+
+ private static final class StringOrDrawable {
+ public String string;
+ public Drawable drawable;
+
+ public StringOrDrawable(String string) {
+ this.string = string;
+ }
+
+ public StringOrDrawable(Drawable drawable) {
+ this.drawable = drawable;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index f4fb0b925b07..5b005237e5d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -604,7 +604,7 @@ public class NotificationContentView extends FrameLayout {
}
int expandedVisualType = getVisualTypeForHeight(height);
int collapsedVisualType = getVisualTypeForHeight(
- mContainingNotification.getMinExpandHeight());
+ mContainingNotification.getCollapsedHeight());
return mTransformationStartVisibleType == collapsedVisualType
? expandedVisualType
: collapsedVisualType;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 45a24a0b3822..3c464d5a1819 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -16,28 +16,35 @@
package com.android.systemui.statusbar;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.app.INotificationManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewAnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
+import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.tuner.TunerService;
/**
@@ -46,6 +53,8 @@ import com.android.systemui.tuner.TunerService;
public class NotificationGuts extends LinearLayout implements TunerService.Tunable {
public static final String SHOW_SLIDER = "show_importance_slider";
+ private static final long CLOSE_GUTS_DELAY = 8000;
+
private Drawable mBackground;
private int mClipTopAmount;
private int mActualHeight;
@@ -59,10 +68,35 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
private RadioButton mSilent;
private RadioButton mReset;
+ private Handler mHandler;
+ private Runnable mFalsingCheck;
+ private boolean mNeedsFalsingProtection;
+ private OnGutsClosedListener mListener;
+
+ public interface OnGutsClosedListener {
+ public void onGutsClosed(NotificationGuts guts);
+ }
+
public NotificationGuts(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
TunerService.get(mContext).addTunable(this, SHOW_SLIDER);
+ mHandler = new Handler();
+ mFalsingCheck = new Runnable() {
+ @Override
+ public void run() {
+ if (mNeedsFalsingProtection && mExposed) {
+ closeControls(-1 /* x */, -1 /* y */, true /* notify */);
+ }
+ }
+ };
+ }
+
+ public void resetFalsingCheck() {
+ mHandler.removeCallbacks(mFalsingCheck);
+ if (mNeedsFalsingProtection && mExposed) {
+ mHandler.postDelayed(mFalsingCheck, CLOSE_GUTS_DELAY);
+ }
}
@Override
@@ -130,30 +164,23 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
importanceSlider.setVisibility(View.VISIBLE);
importanceButtons.setVisibility(View.GONE);
} else {
- int userImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ mStartingImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
try {
- userImportance =
+ mStartingImportance =
mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
} catch (RemoteException e) {}
- bindToggles(importanceButtons, userImportance, systemApp);
+ bindToggles(importanceButtons, mStartingImportance, systemApp);
importanceButtons.setVisibility(View.VISIBLE);
importanceSlider.setVisibility(View.GONE);
}
}
+ public boolean hasImportanceChanged() {
+ return mStartingImportance != getSelectedImportance();
+ }
+
void saveImportance(final StatusBarNotification sbn) {
- int progress;
- if (mSeekBar!= null && mSeekBar.isShown()) {
- progress = mSeekBar.getProgress();
- } else {
- if (mBlock.isChecked()) {
- progress = NotificationListenerService.Ranking.IMPORTANCE_NONE;
- } else if (mSilent.isChecked()) {
- progress = NotificationListenerService.Ranking.IMPORTANCE_LOW;
- } else {
- progress = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
- }
- }
+ int progress = getSelectedImportance();
MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
progress - mStartingImportance);
try {
@@ -163,8 +190,29 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
}
}
+ private int getSelectedImportance() {
+ if (mSeekBar!= null && mSeekBar.isShown()) {
+ return mSeekBar.getProgress();
+ } else {
+ if (mBlock.isChecked()) {
+ return NotificationListenerService.Ranking.IMPORTANCE_NONE;
+ } else if (mSilent.isChecked()) {
+ return NotificationListenerService.Ranking.IMPORTANCE_LOW;
+ } else {
+ return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ }
+ }
+ }
+
private void bindToggles(final View importanceButtons, final int importance,
final boolean systemApp) {
+ ((RadioGroup) importanceButtons).setOnCheckedChangeListener(
+ new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ resetFalsingCheck();
+ }
+ });
mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
mReset = (RadioButton) importanceButtons.findViewById(R.id.reset_importance);
@@ -198,6 +246,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ resetFalsingCheck();
if (progress < minProgress) {
seekBar.setProgress(minProgress);
progress = minProgress;
@@ -210,7 +259,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
- // no-op
+ resetFalsingCheck();
}
@Override
@@ -256,6 +305,38 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
mSeekBar.setProgress(mStartingImportance);
}
+ public void closeControls(int x, int y, boolean notify) {
+ if (getWindowToken() == null) {
+ if (notify && mListener != null) {
+ mListener.onGutsClosed(this);
+ }
+ return;
+ }
+ if (x == -1 || y == -1) {
+ x = (getLeft() + getRight()) / 2;
+ y = (getTop() + getHeight() / 2);
+ }
+ final double horz = Math.max(getWidth() - x, x);
+ final double vert = Math.max(getHeight() - y, y);
+ final float r = (float) Math.hypot(horz, vert);
+ final Animator a = ViewAnimationUtils.createCircularReveal(this,
+ x, y, r, 0);
+ a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+ a.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ setVisibility(View.GONE);
+ }
+ });
+ a.start();
+ setExposed(false, mNeedsFalsingProtection);
+ if (notify && mListener != null) {
+ mListener.onGutsClosed(this);
+ }
+ }
+
public void setActualHeight(int actualHeight) {
mActualHeight = actualHeight;
invalidate();
@@ -277,8 +358,18 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
return false;
}
- public void setExposed(boolean exposed) {
+ public void setClosedListener(OnGutsClosedListener listener) {
+ mListener = listener;
+ }
+
+ public void setExposed(boolean exposed, boolean needsFalsingProtection) {
mExposed = exposed;
+ mNeedsFalsingProtection = needsFalsingProtection;
+ if (mExposed && mNeedsFalsingProtection) {
+ resetFalsingCheck();
+ } else {
+ mHandler.removeCallbacks(mFalsingCheck);
+ }
}
public boolean areGutsExposed() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index c70aad2d4198..06d79a7f9124 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -131,11 +131,8 @@ public class NotificationHeaderUtil {
mComparators.add(HeaderProcessor.forTextView(mRow,
com.android.internal.R.id.app_name_text));
mComparators.add(HeaderProcessor.forTextView(mRow,
- com.android.internal.R.id.header_sub_text));
- mComparators.add(HeaderProcessor.forTextView(mRow,
- com.android.internal.R.id.header_content_info));
- mDividers.add(com.android.internal.R.id.sub_text_divider);
- mDividers.add(com.android.internal.R.id.content_info_divider);
+ com.android.internal.R.id.header_text));
+ mDividers.add(com.android.internal.R.id.header_text_divider);
mDividers.add(com.android.internal.R.id.time_divider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index a3e78c165b2f..a5ebbbab36b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -41,7 +41,7 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
/**
* Called when a notification is slid back over the gear.
*/
- public void onSettingsIconRowReset(NotificationSettingsIconRow row);
+ public void onSettingsIconRowReset(ExpandableNotificationRow row);
}
private ExpandableNotificationRow mParent;
@@ -92,9 +92,9 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
mAnimating = false;
mSnapping = false;
mDismissing = false;
- setIconLocation(true /* on left */);
+ setIconLocation(true /* on left */, true /* force */);
if (mListener != null) {
- mListener.onSettingsIconRowReset(this);
+ mListener.onSettingsIconRowReset(mParent);
}
}
@@ -104,6 +104,7 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
public void setNotificationRowParent(ExpandableNotificationRow parent) {
mParent = parent;
+ setIconLocation(mOnLeft, true /* force */);
}
public void setAppName(String appName) {
@@ -183,7 +184,7 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
if (isIconLocationChange(transX)) {
setGearAlpha(0f);
}
- setIconLocation(transX > 0 /* fromLeft */);
+ setIconLocation(transX > 0 /* fromLeft */, false /* force */);
mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1);
mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
@@ -220,12 +221,20 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
mFadeAnimator.start();
}
- public void setIconLocation(boolean onLeft) {
- if (onLeft == mOnLeft || mSnapping) {
- // Same side? Do nothing.
+ @Override
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ setIconLocation(mOnLeft, true /* force */);
+ }
+
+ public void setIconLocation(boolean onLeft, boolean force) {
+ if ((!force && onLeft == mOnLeft) || mSnapping || mParent == null) {
+ // Do nothing
return;
}
- setTranslationX(onLeft ? 0 : (mParent.getWidth() - mHorizSpaceForGear));
+ final boolean isRtl = mParent.isLayoutRtl();
+ final float left = isRtl ? -(mParent.getWidth() - mHorizSpaceForGear) : 0;
+ final float right = isRtl ? 0 : (mParent.getWidth() - mHorizSpaceForGear);
+ setTranslationX(onLeft ? left : right);
mOnLeft = onLeft;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
index 63ee0c02ba63..41eed565506d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
@@ -113,7 +113,8 @@ public class ManagedProfileController {
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
} else {
mContext.unregisterReceiver(mReceiver);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 260c9697c293..ec45d604b829 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -182,7 +182,7 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape) {
for (int i = 0; i < buttons.length; i++) {
- inflateButton(buttons[i], parent, landscape);
+ inflateButton(buttons[i], parent, landscape, i);
}
}
@@ -195,7 +195,8 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
}
@Nullable
- protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
+ protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,
+ int indexInParent) {
LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
float size = extractSize(buttonSpec);
String button = extractButton(buttonSpec);
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 56a7dbed52cb..68593484a862 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -76,6 +76,8 @@ public class NavigationBarView extends LinearLayout {
private Drawable mHomeDefaultIcon, mHomeCarModeIcon;
private Drawable mRecentIcon;
private Drawable mDockedIcon;
+ private Drawable mImeIcon;
+ private Drawable mMenuIcon;
private NavigationBarGestureHelper mGestureHelper;
private DeadZone mDeadZone;
@@ -270,7 +272,8 @@ public class NavigationBarView extends LinearLayout {
}
private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
- if (oldConfig.orientation != newConfig.orientation) {
+ if (oldConfig.orientation != newConfig.orientation
+ || oldConfig.densityDpi != newConfig.densityDpi) {
mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
}
if (oldConfig.densityDpi != newConfig.densityDpi) {
@@ -280,8 +283,10 @@ public class NavigationBarView extends LinearLayout {
mBackAltLandIcon = mBackAltIcon;
mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
-
mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
+ mMenuIcon = ctx.getDrawable(R.drawable.ic_sysbar_menu);
+ mImeIcon = ctx.getDrawable(R.drawable.ic_ime_switcher_default);
+
updateCarModeIcons(ctx);
}
}
@@ -348,9 +353,11 @@ public class NavigationBarView extends LinearLayout {
final boolean showImeButton = ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
+ getImeSwitchButton().setImageDrawable(mImeIcon);
// Update menu button in case the IME state has changed.
setMenuVisibility(mShowMenu, true);
+ getMenuButton().setImageDrawable(mMenuIcon);
setDisabledFlags(mDisabledFlags, true);
}
@@ -595,14 +602,12 @@ public class NavigationBarView extends LinearLayout {
super.onConfigurationChanged(newConfig);
boolean uiCarModeChanged = updateCarMode(newConfig);
updateTaskSwitchHelper();
- if (uiCarModeChanged) {
- // uiMode changed either from carmode or to carmode.
- // replace the nav bar button icons based on which mode
- // we are switching to.
- setNavigationIconHints(mNavigationIconHints, true);
- }
updateIcons(getContext(), mConfiguration, newConfig);
updateRecentsIcon();
+ if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi) {
+ // If car mode or density changes, we need to reset the icons.
+ setNavigationIconHints(mNavigationIconHints, true);
+ }
mConfiguration.updateFrom(newConfig);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index c563eb606663..bf58592c7ca9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -755,7 +755,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
- mStackScroller.setGearDisplayedListener(getGearDisplayedListener());
mStackScroller.setPhoneStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setHeadsUpManager(mHeadsUpManager);
@@ -3304,10 +3303,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
protected void loadDimens() {
final Resources res = mContext.getResources();
+ int oldBarHeight = mNaturalBarHeight;
mNaturalBarHeight = res.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
-
- mMaxAllowedKeyguardNotifications = res.getInteger(R.integer.keyguard_max_notification_count);
+ if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) {
+ mStatusBarWindowManager.setBarHeight(mNaturalBarHeight);
+ }
+ mMaxAllowedKeyguardNotifications = res.getInteger(
+ R.integer.keyguard_max_notification_count);
if (DEBUG) Log.v(TAG, "updateResources");
}
@@ -4194,6 +4197,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
+ public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
+ mLeaveOpenOnKeyguardHide = true;
+ dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */);
+ }
+
+ @Override
protected void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) {
mLeaveOpenOnKeyguardHide = true;
showBouncer();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index c883cc9284db..0ac2e7c4b8cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -137,7 +137,8 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
// listen for user / profile change.
@@ -507,7 +508,8 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
updateSimState(intent);
} else if (action.equals(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED)) {
updateTTY(intent);
- } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED)) {
+ } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) ||
+ action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
updateQuietState();
updateManagedProfile();
} else if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index f3aba4f81ce0..e8170fb5dc26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -309,7 +309,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
public void setupHost(final QSTileHost host) {
mHost = host;
- host.setHeaderView(this);
+ host.setHeaderView(mExpandIndicator);
mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
mHeaderQsPanel.setHost(host, null /* No customization in header */);
setUserInfoController(host.getUserInfoController());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index b271380e496c..888e19c50f38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -323,6 +323,11 @@ public class StatusBarWindowManager implements RemoteInputController.Callback {
apply(mCurrentState);
}
+ public void setBarHeight(int barHeight) {
+ mBarHeight = barHeight;
+ apply(mCurrentState);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("StatusBarWindowManager state:");
pw.println(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 6a2ecf4e6b0b..ebfa0183f8b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -226,6 +226,10 @@ public class StatusBarWindowView extends FrameLayout {
return false;
}
}
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mStackScrollLayout.closeControlsIfOutsideTouch(ev);
+ }
+
return super.dispatchTouchEvent(ev);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index ab44b6a277ee..ea0bdf29c25c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -23,6 +23,7 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -52,6 +53,7 @@ import com.android.settingslib.RestrictedLockUtils;
import com.android.systemui.BitmapHelper;
import com.android.systemui.GuestResumeSessionReceiver;
import com.android.systemui.R;
+import com.android.systemui.SystemUISecondaryUserService;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.statusbar.phone.ActivityStarter;
@@ -101,6 +103,8 @@ public class UserSwitcherController {
private boolean mSimpleUserSwitcher;
private boolean mAddUsersWhenLocked;
private boolean mPauseRefreshUsers;
+ private int mSecondaryUser = UserHandle.USER_NULL;
+ private Intent mSecondaryUserServiceIntent;
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
@@ -121,6 +125,8 @@ public class UserSwitcherController {
mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
null /* permission */, null /* scheduler */);
+ mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
+
filter = new IntentFilter();
filter.addAction(ACTION_REMOVE_GUEST);
filter.addAction(ACTION_LOGOUT_USER);
@@ -477,6 +483,20 @@ public class UserSwitcherController {
}
notifyAdapters();
+ // Disconnect from the old secondary user's service
+ if (mSecondaryUser != UserHandle.USER_NULL) {
+ context.stopServiceAsUser(mSecondaryUserServiceIntent,
+ UserHandle.of(mSecondaryUser));
+ mSecondaryUser = UserHandle.USER_NULL;
+ }
+ // Connect to the new secondary user's service (purely to ensure that a persistent
+ // SystemUI application is created for that user)
+ if (userInfo != null && !userInfo.isPrimary()) {
+ context.startServiceAsUser(mSecondaryUserServiceIntent,
+ UserHandle.of(userInfo.id));
+ mSecondaryUser = userInfo.id;
+ }
+
if (UserManager.isSplitSystemUser() && userInfo != null && !userInfo.isGuest()
&& userInfo.id != UserHandle.USER_SYSTEM) {
showLogoutNotification(currentId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index dc567fc20113..ee483e5a40e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -592,7 +592,7 @@ public class NotificationChildrenContainer extends ViewGroup {
public float getGroupExpandFraction() {
int visibleChildrenExpandedHeight = getVisibleChildrenExpandHeight();
- int minExpandHeight = getMinExpandHeight();
+ int minExpandHeight = getCollapsedHeight();
float factor = (mActualHeight - minExpandHeight)
/ (float) (visibleChildrenExpandedHeight - minExpandHeight);
return Math.max(0.0f, Math.min(1.0f, factor));
@@ -618,11 +618,14 @@ public class NotificationChildrenContainer extends ViewGroup {
}
public int getMinHeight() {
- return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
+ return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
}
- public int getMinExpandHeight() {
- int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+ public int getCollapsedHeight() {
+ return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
+ }
+
+ private int getMinHeight(int maxAllowedVisibleChildren) {
int minExpandHeight = mNotificationHeaderHeight;
int visibleChildren = 0;
boolean firstChild = true;
@@ -637,7 +640,7 @@ public class NotificationChildrenContainer extends ViewGroup {
firstChild = false;
}
ExpandableNotificationRow child = mChildren.get(i);
- minExpandHeight += child.getMinHeight();
+ minExpandHeight += child.getSingleLineView().getHeight();
visibleChildren++;
}
minExpandHeight += mCollapsedBottompadding;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index b5030e66e9c5..fa37e2257a61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -60,6 +60,7 @@ import com.android.systemui.statusbar.DismissView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.NotificationGuts;
import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.NotificationSettingsIconRow;
import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener;
@@ -220,7 +221,6 @@ public class NotificationStackScrollLayout extends ViewGroup
*/
private int mMaxScrollAfterExpand;
private SwipeHelper.LongPressListener mLongPressListener;
- private GearDisplayedListener mGearDisplayedListener;
private NotificationSettingsIconRow mCurrIconRow;
private View mTranslatingParentView;
@@ -374,8 +374,12 @@ public class NotificationStackScrollLayout extends ViewGroup
}
@Override
- public void onSettingsIconRowReset(NotificationSettingsIconRow row) {
- mSwipeHelper.setSnappedToGear(false);
+ public void onSettingsIconRowReset(ExpandableNotificationRow row) {
+ if (mTranslatingParentView != null && row == mTranslatingParentView) {
+ mSwipeHelper.setSnappedToGear(false);
+ mGearExposedView = null;
+ mTranslatingParentView = null;
+ }
}
@Override
@@ -669,10 +673,6 @@ public class NotificationStackScrollLayout extends ViewGroup
mLongPressListener = listener;
}
- public void setGearDisplayedListener(GearDisplayedListener listener) {
- mGearDisplayedListener = listener;
- }
-
public void setQsContainer(ViewGroup qsContainer) {
mQsContainer = qsContainer;
}
@@ -737,17 +737,9 @@ public class NotificationStackScrollLayout extends ViewGroup
// We start the swipe and snap back in the same frame, we don't want any animation
mDragAnimPendingChildren.remove(animView);
}
-
- if (mCurrIconRow != null) {
- if (targetLeft == 0) {
- mCurrIconRow.resetState();
- mCurrIconRow = null;
- if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
- mGearExposedView = null;
- }
- } else {
- mSwipeHelper.setSnappedToGear(true);
- }
+ if (mCurrIconRow != null && targetLeft == 0) {
+ mCurrIconRow.resetState();
+ mCurrIconRow = null;
}
}
@@ -926,7 +918,7 @@ public class NotificationStackScrollLayout extends ViewGroup
int positionInLinearLayout = getPositionInLinearLayout(v);
int targetScroll = positionInLinearLayout + expandableView.getActualHeight() +
- mBottomInset - getHeight() + getTopPadding();
+ getImeInset() - getHeight() + getTopPadding();
if (mOwnScrollY < targetScroll) {
mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
mDontReportNextOverScroll = true;
@@ -936,8 +928,7 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mBottomInset = Math.max(0, insets.getSystemWindowInsetBottom()
- - (getRootView().getHeight() - getHeight()));
+ mBottomInset = insets.getSystemWindowInsetBottom();
int range = getScrollRange();
if (mOwnScrollY > range) {
@@ -995,7 +986,8 @@ public class NotificationStackScrollLayout extends ViewGroup
}
public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) {
- mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration);
+ mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration,
+ true /* isDismissAll */);
}
public void snapViewIfNeeded(View child) {
@@ -1506,23 +1498,17 @@ public class NotificationStackScrollLayout extends ViewGroup
}
private int getScrollRange() {
- int scrollRange = 0;
- ExpandableView firstChild = (ExpandableView) getFirstChildNotGone();
- if (firstChild != null) {
- int contentHeight = getContentHeight();
- scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize
- + mBottomStackSlowDownHeight);
- if (scrollRange > 0) {
- int firstChildMaxExpandHeight = getMaxExpandHeight(firstChild);
- // We want to at least be able collapse the first item and not ending in a weird
- // end state.
- scrollRange = Math.max(scrollRange, firstChildMaxExpandHeight
- - firstChild.getMinHeight());
- }
- }
- int imeOverlap = Math.max(0,
- getContentHeight() - (getHeight() - mBottomInset));
- return scrollRange + imeOverlap;
+ int contentHeight = getContentHeight();
+ int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize
+ + mBottomStackSlowDownHeight);
+ int imeInset = getImeInset();
+ scrollRange += Math.min(imeInset, Math.max(0,
+ getContentHeight() - (getHeight() - imeInset)));
+ return scrollRange;
+ }
+
+ private int getImeInset() {
+ return Math.max(0, mBottomInset - (getRootView().getHeight() - getHeight()));
}
/**
@@ -1947,7 +1933,7 @@ public class NotificationStackScrollLayout extends ViewGroup
public int getPeekHeight() {
final ExpandableView firstChild = getFirstChildNotGone();
- final int firstChildMinHeight = firstChild != null ? (int) firstChild.getMinHeight()
+ final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
: mCollapsedSize;
return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
+ mBottomStackSlowDownHeight;
@@ -3209,9 +3195,6 @@ public class NotificationStackScrollLayout extends ViewGroup
disableClipOptimization();
}
handleDismissAllClipping();
- if (mCurrIconRow != null && mCurrIconRow.isVisible()) {
- mCurrIconRow.getNotificationParent().animateTranslateNotification(0 /* left target */);
- }
}
private void handleDismissAllClipping() {
@@ -3470,16 +3453,11 @@ public class NotificationStackScrollLayout extends ViewGroup
public void flingTopOverscroll(float velocity, boolean open);
}
- /**
- * A listener that is notified when the gear is shown behind a notification.
- */
- public interface GearDisplayedListener {
- void onGearDisplayed(ExpandableNotificationRow row);
- }
-
private class NotificationSwipeHelper extends SwipeHelper {
- private static final long GEAR_SHOW_DELAY = 60;
+ private static final long SHOW_GEAR_DELAY = 60;
+ private static final long COVER_GEAR_DELAY = 4000;
private CheckForDrag mCheckForDrag;
+ private Runnable mFalsingCheck;
private Handler mHandler;
private boolean mGearSnappedTo;
private boolean mGearSnappedOnLeft;
@@ -3487,6 +3465,12 @@ public class NotificationStackScrollLayout extends ViewGroup
public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
super(swipeDirection, callback, context);
mHandler = new Handler();
+ mFalsingCheck = new Runnable() {
+ @Override
+ public void run() {
+ resetExposedGearView(true /* animate */, true /* force */);
+ }
+ };
}
@Override
@@ -3501,9 +3485,10 @@ public class NotificationStackScrollLayout extends ViewGroup
}
mCheckForDrag = null;
mCurrIconRow = null;
+ mHandler.removeCallbacks(mFalsingCheck);
// Slide back any notifications that might be showing a gear
- resetExposedGearView();
+ resetExposedGearView(true /* animate */, false /* force */);
if (currView instanceof ExpandableNotificationRow) {
// Set the listener for the current row's gear
@@ -3514,6 +3499,8 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public void onMoveUpdate(View view, float translation, float delta) {
+ mHandler.removeCallbacks(mFalsingCheck);
+
if (mCurrIconRow != null) {
mCurrIconRow.setSnapping(false); // If we're moving, we're not snapping.
@@ -3532,7 +3519,8 @@ public class NotificationStackScrollLayout extends ViewGroup
} else {
// Check scheduled, reset alpha and update location; check will fade it in
mCurrIconRow.setGearAlpha(0f);
- mCurrIconRow.setIconLocation(translation > 0 /* onLeft */);
+ mCurrIconRow.setIconLocation(translation > 0 /* onLeft */,
+ false /* force */);
}
}
}
@@ -3547,10 +3535,10 @@ public class NotificationStackScrollLayout extends ViewGroup
}
@Override
- public void dismissChild(final View view, float velocity) {
- super.dismissChild(view, velocity);
- cancelCheckForDrag();
- setSnappedToGear(false);
+ public void dismissChild(final View view, float velocity,
+ boolean useAccelerateInterpolator) {
+ super.dismissChild(view, velocity, useAccelerateInterpolator);
+ handleGearCoveredOrDismissed();
}
@Override
@@ -3558,11 +3546,17 @@ public class NotificationStackScrollLayout extends ViewGroup
super.snapChild(animView, targetLeft, velocity);
onDragCancelled(animView);
if (targetLeft == 0) {
- cancelCheckForDrag();
- setSnappedToGear(false);
+ handleGearCoveredOrDismissed();
}
}
+ private void handleGearCoveredOrDismissed() {
+ cancelCheckForDrag();
+ setSnappedToGear(false);
+ if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
+ mGearExposedView = null;
+ }
+ }
@Override
public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
@@ -3584,7 +3578,8 @@ public class NotificationStackScrollLayout extends ViewGroup
snapChild(animView, 0 /* leftTarget */, velocity);
} else if (isDismissGesture(ev)) {
// Gesture is a dismiss that's not towards the gear
- dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+ dismissChild(animView, velocity,
+ !swipedFastEnough() /* useAccelerateInterpolator */);
} else {
// Didn't move enough to dismiss or cover, snap to the gear
snapToGear(animView, velocity);
@@ -3609,7 +3604,8 @@ public class NotificationStackScrollLayout extends ViewGroup
private void dismissOrSnapBack(View animView, float velocity, MotionEvent ev) {
if (isDismissGesture(ev)) {
- dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+ dismissChild(animView, velocity,
+ !swipedFastEnough() /* useAccelerateInterpolator */);
} else {
snapChild(animView, 0 /* leftTarget */, velocity);
}
@@ -3620,19 +3616,29 @@ public class NotificationStackScrollLayout extends ViewGroup
final float target = mCurrIconRow.isIconOnLeft() ? snapBackThreshold
: -snapBackThreshold;
mGearExposedView = mTranslatingParentView;
- if (mGearDisplayedListener != null
- && (animView instanceof ExpandableNotificationRow)) {
- mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
+ if (animView instanceof ExpandableNotificationRow) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+ ((ExpandableNotificationRow) animView).getStatusBarNotification()
+ .getPackageName());
}
if (mCurrIconRow != null) {
mCurrIconRow.setSnapping(true);
setSnappedToGear(true);
}
onDragCancelled(animView);
+
+ // If we're on the lockscreen we want to false this.
+ if (mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+ mHandler.removeCallbacks(mFalsingCheck);
+ mHandler.postDelayed(mFalsingCheck, COVER_GEAR_DELAY);
+ }
super.snapChild(animView, target, velocity);
}
private boolean swipedEnoughToShowGear(View animView) {
+ if (mTranslatingParentView == null) {
+ return false;
+ }
final float snapBackThreshold = getSpaceForGear(animView);
final float translation = getTranslation(animView);
final boolean fromLeft = translation > 0;
@@ -3648,10 +3654,7 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public Animator getViewTranslationAnimator(View v, float target,
AnimatorUpdateListener listener) {
- if (mDismissAllInProgress) {
- // When dismissing all, we translate the entire view instead.
- return super.getViewTranslationAnimator(v, target, listener);
- } else if (v instanceof ExpandableNotificationRow) {
+ if (v instanceof ExpandableNotificationRow) {
return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
} else {
return super.getViewTranslationAnimator(v, target, listener);
@@ -3660,21 +3663,42 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public void setTranslation(View v, float translate) {
- if (mDismissAllInProgress) {
- // When dismissing all, we translate the entire view instead.
- super.setTranslation(v, translate);
- } else {
- ((ExpandableView) v).setTranslation(translate);
- }
+ ((ExpandableView) v).setTranslation(translate);
}
@Override
public float getTranslation(View v) {
- if (mDismissAllInProgress) {
- // When dismissing all, we translate the entire view instead.
- return super.getTranslation(v);
- } else {
- return ((ExpandableView) v).getTranslation();
+ return ((ExpandableView) v).getTranslation();
+ }
+
+ public void closeControlsIfOutsideTouch(MotionEvent ev) {
+ NotificationGuts guts = mPhoneStatusBar.getExposedGuts();
+ View view = null;
+ int height = 0;
+ if (guts != null) {
+ // Checking guts
+ view = guts;
+ height = guts.getActualHeight();
+ } else if (mCurrIconRow != null && mCurrIconRow.isVisible()
+ && mTranslatingParentView != null) {
+ // Checking gear
+ view = mTranslatingParentView;
+ height = ((ExpandableView) mTranslatingParentView).getActualHeight();
+ }
+ if (view != null) {
+ final int rx = (int) ev.getRawX();
+ final int ry = (int) ev.getRawY();
+
+ getLocationOnScreen(mTempInt2);
+ int[] location = new int[2];
+ view.getLocationOnScreen(location);
+ final int x = location[0] - mTempInt2[0];
+ final int y = location[1] - mTempInt2[1];
+ Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
+ if (!rect.contains((int) rx, (int) ry)) {
+ // Touch was outside visible guts / gear notification, close what's visible
+ mPhoneStatusBar.dismissPopups(-1, -1, true /* resetGear */, true /* animate */);
+ }
}
}
@@ -3711,7 +3735,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private void checkForDrag() {
if (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag)) {
mCheckForDrag = new CheckForDrag();
- mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY);
+ mHandler.postDelayed(mCheckForDrag, SHOW_GEAR_DELAY);
}
}
@@ -3725,6 +3749,9 @@ public class NotificationStackScrollLayout extends ViewGroup
private final class CheckForDrag implements Runnable {
@Override
public void run() {
+ if (mTranslatingParentView == null) {
+ return;
+ }
final float translation = getTranslation(mTranslatingParentView);
final float absTransX = Math.abs(translation);
final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
@@ -3740,20 +3767,24 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
- private void resetExposedGearView() {
- if (mGearExposedView == null || mGearExposedView == mTranslatingParentView) {
+ public void resetExposedGearView(boolean animate, boolean force) {
+ if (mGearExposedView == null
+ || (!force && mGearExposedView == mTranslatingParentView)) {
// If no gear is showing or it's showing for this view we do nothing.
return;
}
-
final View prevGearExposedView = mGearExposedView;
+ if (animate) {
+ Animator anim = getViewTranslationAnimator(prevGearExposedView,
+ 0 /* leftTarget */, null /* updateListener */);
+ if (anim != null) {
+ anim.start();
+ }
+ } else if (mGearExposedView instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) mGearExposedView).resetTranslation();
+ }
mGearExposedView = null;
mGearSnappedTo = false;
- Animator anim = getViewTranslationAnimator(prevGearExposedView,
- 0 /* leftTarget */, null /* updateListener */);
- if (anim != null) {
- anim.start();
- }
}
}
@@ -3769,6 +3800,14 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ public void resetExposedGearView(boolean animate, boolean force) {
+ mSwipeHelper.resetExposedGearView(animate, force);
+ }
+
+ public void closeControlsIfOutsideTouch(MotionEvent ev) {
+ mSwipeHelper.closeControlsIfOutsideTouch(ev);
+ }
+
static class AnimationEvent {
static AnimationFilter[] FILTERS = new AnimationFilter[] {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 4c94fe93cbdc..c7333c2721b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -368,7 +368,7 @@ public class StackScrollAlgorithm {
childViewState.location = StackViewState.LOCATION_UNKNOWN;
paddingAfterChild = getPaddingAfterChild(algorithmState, child);
int childHeight = getMaxAllowedChildHeight(child);
- int minHeight = child.getMinHeight();
+ int collapsedHeight = child.getCollapsedHeight();
childViewState.yTranslation = currentYPosition;
if (i == 0) {
updateFirstChildHeight(child, childViewState, childHeight, ambientState);
@@ -384,7 +384,7 @@ public class StackScrollAlgorithm {
// According to the regular scroll view we are fully translated out of the
// bottom of the screen so we are fully in the bottom stack
updateStateForChildFullyInBottomStack(algorithmState,
- bottomStackStart, childViewState, minHeight, ambientState, child);
+ bottomStackStart, childViewState, collapsedHeight, ambientState, child);
} else {
// According to the regular scroll view we are currently translating out of /
// into the bottom of the screen
@@ -475,17 +475,17 @@ public class StackScrollAlgorithm {
float newTranslation = Math.max(ambientState.getTopPadding()
+ ambientState.getStackTranslation(), childState.yTranslation);
childState.height = (int) Math.max(childState.height - (newTranslation
- - childState.yTranslation), row.getMinHeight());
+ - childState.yTranslation), row.getCollapsedHeight());
childState.yTranslation = newTranslation;
}
private void clampHunToMaxTranslation(AmbientState ambientState, ExpandableNotificationRow row,
StackViewState childState) {
float newTranslation;
- float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getMinHeight();
+ float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getCollapsedHeight();
newTranslation = Math.min(childState.yTranslation, bottomPosition);
childState.height = (int) Math.max(childState.height
- - (childState.yTranslation - newTranslation), row.getMinHeight());
+ - (childState.yTranslation - newTranslation), row.getCollapsedHeight());
childState.yTranslation = newTranslation;
}
@@ -534,10 +534,10 @@ public class StackScrollAlgorithm {
float offset = mBottomStackIndentationFunctor.getValue(algorithmState.partialInBottom);
algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
int newHeight = childHeight;
- if (childHeight > child.getMinHeight()) {
+ if (childHeight > child.getCollapsedHeight()) {
newHeight = (int) Math.max(Math.min(transitioningPositionStart + offset -
getPaddingAfterChild(algorithmState, child) - currentYPosition, childHeight),
- child.getMinHeight());
+ child.getCollapsedHeight());
childViewState.height = newHeight;
}
childViewState.yTranslation = transitioningPositionStart + offset - newHeight
@@ -547,7 +547,7 @@ public class StackScrollAlgorithm {
private void updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
float transitioningPositionStart, StackViewState childViewState,
- int minHeight, AmbientState ambientState, ExpandableView child) {
+ int collapsedHeight, AmbientState ambientState, ExpandableView child) {
float currentYPosition;
algorithmState.itemsInBottomStack += 1.0f;
if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
@@ -568,16 +568,14 @@ public class StackScrollAlgorithm {
childViewState.location = StackViewState.LOCATION_BOTTOM_STACK_HIDDEN;
currentYPosition = ambientState.getInnerHeight();
}
- childViewState.height = minHeight;
- childViewState.yTranslation = currentYPosition - minHeight;
+ childViewState.height = collapsedHeight;
+ childViewState.yTranslation = currentYPosition - collapsedHeight;
}
/**
* Update the height of the first child i.e clamp it to the bottom stack
*
- *
-
* @param child the child to update
* @param childViewState the viewstate of the child
* @param childHeight the height of the child
@@ -591,7 +589,7 @@ public class StackScrollAlgorithm {
mBottomStackSlowDownLength + ambientState.getScrollY();
// Collapse and expand the first child while the shade is being expanded
childViewState.height = (int) Math.max(Math.min(bottomPeekStart, (float) childHeight),
- child.getMinHeight());
+ child.getCollapsedHeight());
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index b5c1f5739e65..fe5409041d12 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -265,11 +265,7 @@ public class PipManager {
*/
private void showPipOverlay() {
if (DEBUG) Log.d(TAG, "showPipOverlay()");
- Intent intent = new Intent(mContext, PipOverlayActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(PINNED_STACK_ID);
- mContext.startActivity(intent, options.toBundle());
+ PipOverlayActivity.showPipOverlay(mContext);
}
/**
@@ -635,7 +631,7 @@ public class PipManager {
void onPipActivityClosed();
/** Invoked when the PIP menu gets shown. */
void onShowPipMenu();
- /** Invoked when the PIPed activity is returned back to the fullscreen. */
+ /** Invoked when the PIPed activity is about to return back to the fullscreen. */
void onMoveToFullscreen();
/** Invoked when we are above to start resizing the Pip. */
void onPipResizeAboutToStart();
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index c54e73a7cda6..854e09d9d1a6 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -30,6 +30,7 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
private final PipManager mPipManager = PipManager.getInstance();
private PipControlsView mPipControlsView;
+ private boolean mRestorePipSizeWhenClose;
@Override
protected void onCreate(Bundle bundle) {
@@ -38,12 +39,21 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
mPipManager.addListener(this);
mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
+ mRestorePipSizeWhenClose = true;
+ }
+
+ private void restorePipAndFinish() {
+ if (mRestorePipSizeWhenClose) {
+ // When PIP menu activity is closed, restore to the default position.
+ mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+ }
+ finish();
}
@Override
public void onPause() {
super.onPause();
- finish();
+ restorePipAndFinish();
}
@Override
@@ -55,6 +65,11 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
}
@Override
+ public void onBackPressed() {
+ restorePipAndFinish();
+ }
+
+ @Override
public void onPipEntered() { }
@Override
@@ -67,6 +82,9 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
@Override
public void onMoveToFullscreen() {
+ // Moving PIP to fullscreen is implemented by resizing PINNED_STACK with null bounds.
+ // This conflicts with restoring PIP position, so disable it.
+ mRestorePipSizeWhenClose = false;
finish();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
index 5472ad6718dd..e205ff5749b0 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -35,6 +35,14 @@ import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
public class PipOverlayActivity extends Activity implements PipManager.Listener {
private static final long SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS = 4000;
+ /**
+ * A flag to ensure the single instance of PipOverlayActivity to prevent it from restarting.
+ * Note that {@link PipManager} moves the PIPed activity to fullscreen if the activity is
+ * restarted. It's because the activity may be started by the Launcher or an intent again,
+ * but we don't want do so for the PipOverlayActivity.
+ */
+ private static boolean sActivityCreated;
+
private final PipManager mPipManager = PipManager.getInstance();
private final Handler mHandler = new Handler();
private View mGuideOverlayView;
@@ -46,9 +54,23 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
}
};
+ /**
+ * Shows PIP overlay UI only if it's not there.
+ */
+ static void showPipOverlay(Context context) {
+ if (!sActivityCreated) {
+ Intent intent = new Intent(context, PipOverlayActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchStackId(PINNED_STACK_ID);
+ context.startActivity(intent, options.toBundle());
+ }
+ }
+
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
+ sActivityCreated = true;
setContentView(R.layout.tv_pip_overlay);
mGuideOverlayView = findViewById(R.id.guide_overlay);
mPipManager.addListener(this);
@@ -71,6 +93,7 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
@Override
protected void onDestroy() {
super.onDestroy();
+ sActivityCreated = false;
mHandler.removeCallbacksAndMessages(null);
mPipManager.removeListener(this);
mPipManager.resumePipResizing(
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
index b90b7279a5b5..47cd8e5a9b44 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
@@ -131,9 +131,9 @@ public class PipRecentsOverlayManager {
* Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
* is focused.
* This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
- * @param hasRecentsFocusable {@code true} if Recents can have focus. (i.e. Has a recent task)
+ * @param allowRecentsFocusable {@code true} if Recents can have focus. (i.e. Has a recent task)
*/
- public void requestFocus(boolean hasRecentsFocusable) {
+ public void requestFocus(boolean allowRecentsFocusable) {
if (!mIsRecentsShown || mIsPipFocusedInRecent) {
return;
}
@@ -143,7 +143,7 @@ public class PipRecentsOverlayManager {
mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
mPipControlsView.requestFocus();
mPipControlsView.startFocusGainAnimation();
- mRecentsView.setVisibility(hasRecentsFocusable ? View.VISIBLE : View.GONE);
+ mRecentsView.setVisibility(allowRecentsFocusable ? View.VISIBLE : View.GONE);
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
index 6a8165942cc0..a30f50775f77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
@@ -198,7 +198,7 @@ public class TileLifecycleManagerTests extends AndroidTestCase {
}
private void waitForCallback(String callback) {
- for (int i = 0; i < 25; i++) {
+ for (int i = 0; i < 50; i++) {
if (mCallbacks.contains(callback)) {
mCallbacks.remove(callback);
return;
@@ -229,7 +229,7 @@ public class TileLifecycleManagerTests extends AndroidTestCase {
}
});
try {
- lock.wait(5000);
+ lock.wait(10000);
} catch (InterruptedException e) {
}
}
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 9beaba301072..2650e5a868d2 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1031,7 +1031,6 @@ public class RenderScript {
- long mDev;
long mContext;
private boolean mDestroyed = false;
@@ -1426,8 +1425,8 @@ public class RenderScript {
RenderScript rs = new RenderScript(ctx);
- rs.mDev = rs.nDeviceCreate();
- rs.mContext = rs.nContextCreate(rs.mDev, flags, sdkVersion, ct.mID);
+ long device = rs.nDeviceCreate();
+ rs.mContext = rs.nContextCreate(device, flags, sdkVersion, ct.mID);
rs.mContextType = ct;
rs.mContextFlags = flags;
rs.mContextSdkVersion = sdkVersion;
@@ -1635,9 +1634,6 @@ public class RenderScript {
}
nContextDestroy();
-
- nDeviceDestroy(mDev);
- mDev = 0;
}
}
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index 6178994cfbe3..be1f899bd08b 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -177,9 +177,9 @@ public class RenderScriptGL extends RenderScript {
mWidth = 0;
mHeight = 0;
- mDev = nDeviceCreate();
+ long device = nDeviceCreate();
int dpi = ctx.getResources().getDisplayMetrics().densityDpi;
- mContext = nContextCreateGL(mDev, 0, sdkVersion,
+ mContext = nContextCreateGL(device, 0, sdkVersion,
mSurfaceConfig.mColorMin, mSurfaceConfig.mColorPref,
mSurfaceConfig.mAlphaMin, mSurfaceConfig.mAlphaPref,
mSurfaceConfig.mDepthMin, mSurfaceConfig.mDepthPref,
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4b96e7a31ccf..27417332f7d1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1262,7 +1262,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
Service service = componentNameToServiceMap.get(componentName);
// Ignore non-encryption-aware services until user is unlocked
- if (!isUnlocked && !installedService.isEncryptionAware()) {
+ if (!isUnlocked && !installedService.isDirectBootAware()) {
Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
continue;
}
@@ -1784,10 +1784,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mEnabledServices.contains(userState.mServiceChangingSoftKeyboardMode);
if (!serviceChangingSoftKeyboardModeIsEnabled) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
- 0,
- userState.mUserId);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+ 0,
+ userState.mUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
userState.mSoftKeyboardShowMode = 0;
userState.mServiceChangingSoftKeyboardMode = null;
}
@@ -2146,7 +2151,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
MagnificationController getMagnificationController() {
synchronized (mLock) {
if (mMagnificationController == null) {
- mMagnificationController = new MagnificationController(mContext, this);
+ mMagnificationController = new MagnificationController(mContext, this, mLock);
mMagnificationController.register();
mMagnificationController.setUserId(mCurrentUserId);
}
@@ -3491,6 +3496,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
reportedWindow.setLayer(window.layer);
reportedWindow.setFocused(window.focused);
reportedWindow.setBoundsInScreen(window.boundsInScreen);
+ reportedWindow.setTitle(window.title);
+ reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
final int parentId = findWindowIdLocked(window.parentToken);
if (parentId >= 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index e15b785ba718..b2196bf946e2 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -72,7 +72,7 @@ class MagnificationController {
*/
private static final float MIN_PERSISTED_SCALE = 2.0f;
- private final Object mLock = new Object();
+ private final Object mLock;
/**
* The current magnification spec. If an animation is running, this
@@ -97,12 +97,13 @@ class MagnificationController {
private int mUserId;
- public MagnificationController(Context context, AccessibilityManagerService ams) {
+ public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) {
mAms = ams;
mContentResolver = context.getContentResolver();
mScreenStateObserver = new ScreenStateObserver(context, this);
mWindowStateObserver = new WindowStateObserver(context, this);
mSpecAnimationBridge = new SpecAnimationBridge(context);
+ mLock = lock;
}
/**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 89b145e2f4c0..f93fb1b0f975 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -164,7 +164,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
onUserStopped(userId);
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
reloadWidgetsMaskedStateForGroup(userId);
- } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
+ } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
+ || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
synchronized (mLock) {
reloadWidgetsMaskedState(userId);
}
@@ -288,7 +289,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
userFilter, null, null);
IntentFilter offModeFilter = new IntentFilter();
- offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+ offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+ offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
offModeFilter, null, null);
@@ -594,27 +596,28 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
final boolean showBadge;
final Intent onClickIntent;
- if (provider.maskedBySuspendedPackage) {
- final long identity = Binder.clearCallingIdentity();
- try {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (provider.maskedBySuspendedPackage) {
UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
showBadge = userInfo.isManagedProfile();
onClickIntent = mDevicePolicyManagerInternal.createPackageSuspendedDialogIntent(
providerPackage, providerUserId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- } else if (provider.maskedByQuietProfile) {
- showBadge = true;
- onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
- providerUserId);
- } else /* provider.maskedByLockedProfile */ {
- showBadge = true;
- onClickIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null,
- providerUserId);
- if (onClickIntent != null) {
- onClickIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ } else if (provider.maskedByQuietProfile) {
+ showBadge = true;
+ onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
+ providerUserId);
+ } else /* provider.maskedByLockedProfile */ {
+ showBadge = true;
+ onClickIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null,
+ providerUserId);
+ if (onClickIntent != null) {
+ onClickIntent.setFlags(FLAG_ACTIVITY_NEW_TASK
+ | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
}
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
for (int j = 0; j < widgetCount; j++) {
@@ -742,8 +745,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
@Override
- public int[] startListening(IAppWidgetHost callbacks, String callingPackage,
- int hostId, List<RemoteViews> updatedViews) {
+ public ParceledListSlice<RemoteViews> startListening(IAppWidgetHost callbacks,
+ String callingPackage, int hostId, int[] appWidgetIds, int[] updatedIds) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
@@ -760,21 +763,21 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// sure the caller can only access hosts it owns.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupOrAddHostLocked(id);
-
host.callbacks = callbacks;
- updatedViews.clear();
-
- ArrayList<Widget> instances = host.widgets;
- int N = instances.size();
- int[] updatedIds = new int[N];
+ int N = appWidgetIds.length;
+ ArrayList<RemoteViews> outViews = new ArrayList<>(N);
+ RemoteViews rv;
+ int added = 0;
for (int i = 0; i < N; i++) {
- Widget widget = instances.get(i);
- updatedIds[i] = widget.appWidgetId;
- updatedViews.add(cloneIfLocalBinder(widget.getEffectiveViewsLocked()));
+ rv = host.getPendingViewsForId(appWidgetIds[i]);
+ if (rv != null) {
+ updatedIds[added] = appWidgetIds[i];
+ outViews.add(rv);
+ added++;
+ }
}
-
- return updatedIds;
+ return new ParceledListSlice<>(outViews);
}
}
@@ -1882,6 +1885,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
+ long requestTime = SystemClock.uptimeMillis();
+ if (widget != null) {
+ widget.lastUpdateTime = requestTime;
+ }
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
return;
@@ -1891,6 +1898,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
args.arg3 = updateViews;
+ args.arg4 = requestTime;
args.argi1 = widget.appWidgetId;
mCallbackHandler.obtainMessage(
@@ -1899,9 +1907,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks,
- int appWidgetId, RemoteViews views) {
+ int appWidgetId, RemoteViews views, long requestTime) {
try {
callbacks.updateAppWidget(appWidgetId, views);
+ host.lastWidgetUpdateTime = requestTime;
} catch (RemoteException re) {
synchronized (mLock) {
Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3398,10 +3407,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Host host = (Host) args.arg1;
IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
RemoteViews views = (RemoteViews) args.arg3;
+ long requestTime = (Long) args.arg4;
final int appWidgetId = args.argi1;
args.recycle();
- handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views);
+ handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views, requestTime);
} break;
case MSG_NOTIFY_PROVIDER_CHANGED: {
@@ -3769,6 +3779,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
int tag = TAG_UNDEFINED; // for use while saving state (the index)
+ long lastWidgetUpdateTime; // last time we were successfully able to send an update.
public int getUserId() {
return UserHandle.getUserId(id.uid);
@@ -3790,6 +3801,23 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
return false;
}
+ /**
+ * Returns the RemoveViews for the provided widget id if an update is pending
+ * for that widget.
+ */
+ public RemoteViews getPendingViewsForId(int appWidgetId) {
+ long updateTime = lastWidgetUpdateTime;
+ int N = widgets.size();
+ for (int i = 0; i < N; i++) {
+ Widget widget = widgets.get(i);
+ if (widget.appWidgetId == appWidgetId
+ && widget.lastUpdateTime > updateTime) {
+ return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
+ }
+ }
+ return null;
+ }
+
@Override
public String toString() {
return "Host{" + id + (zombie ? " Z" : "") + '}';
@@ -3860,6 +3888,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
RemoteViews maskedViews;
Bundle options;
Host host;
+ long lastUpdateTime;
@Override
public String toString() {
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java
index a0b5c154c13f..e98b4aa6e267 100644
--- a/services/core/java/com/android/server/AnyMotionDetector.java
+++ b/services/core/java/com/android/server/AnyMotionDetector.java
@@ -108,63 +108,71 @@ public class AnyMotionDetector {
public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
DeviceIdleCallback callback, float thresholdAngle) {
if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated.");
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mWakeLock.setReferenceCounted(false);
- mHandler = handler;
- mSensorManager = sm;
- mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- mMeasurementInProgress = false;
- mState = STATE_INACTIVE;
- mCallback = callback;
- mThresholdAngle = thresholdAngle;
- mRunningStats = new RunningSignalStats();
- mNumSufficientSamples = (int) Math.ceil(
- ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
- if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples);
+ synchronized (mLock) {
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ mWakeLock.setReferenceCounted(false);
+ mHandler = handler;
+ mSensorManager = sm;
+ mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ mMeasurementInProgress = false;
+ mState = STATE_INACTIVE;
+ mCallback = callback;
+ mThresholdAngle = thresholdAngle;
+ mRunningStats = new RunningSignalStats();
+ mNumSufficientSamples = (int) Math.ceil(
+ ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
+ if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples);
+ }
}
/*
* Acquire accel data until we determine AnyMotion status.
*/
public void checkForAnyMotion() {
- if (DEBUG) Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
+ if (DEBUG) {
+ Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
+ }
if (mState != STATE_ACTIVE) {
- mState = STATE_ACTIVE;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
- mCurrentGravityVector = null;
- mPreviousGravityVector = null;
- startOrientationMeasurement();
+ synchronized (mLock) {
+ mState = STATE_ACTIVE;
+ if (DEBUG) {
+ Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
+ }
+ mCurrentGravityVector = null;
+ mPreviousGravityVector = null;
+ mWakeLock.acquire();
+ startOrientationMeasurementLocked();
+ }
}
}
public void stop() {
if (mState == STATE_ACTIVE) {
- mState = STATE_INACTIVE;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
- if (mMeasurementInProgress) {
- mMeasurementInProgress = false;
- mSensorManager.unregisterListener(mListener);
+ synchronized (mLock) {
+ mState = STATE_INACTIVE;
+ if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
+ if (mMeasurementInProgress) {
+ mMeasurementInProgress = false;
+ mSensorManager.unregisterListener(mListener);
+ }
+ mHandler.removeCallbacks(mMeasurementTimeout);
+ mHandler.removeCallbacks(mSensorRestart);
+ mCurrentGravityVector = null;
+ mPreviousGravityVector = null;
+ mWakeLock.release();
}
- mHandler.removeCallbacks(mMeasurementTimeout);
- mHandler.removeCallbacks(mSensorRestart);
- mWakeLock.release();
- mCurrentGravityVector = null;
- mPreviousGravityVector = null;
}
}
- private void startOrientationMeasurement() {
- if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" +
+ private void startOrientationMeasurementLocked() {
+ if (DEBUG) Slog.d(TAG, "startOrientationMeasurementLocked: mMeasurementInProgress=" +
mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
-
if (!mMeasurementInProgress && mAccelSensor != null) {
if (mSensorManager.registerListener(mListener, mAccelSensor,
SAMPLING_INTERVAL_MILLIS * 1000)) {
- mWakeLock.acquire();
mMeasurementInProgress = true;
mRunningStats.reset();
}
-
Message msg = Message.obtain(mHandler, mMeasurementTimeout);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
@@ -178,7 +186,6 @@ public class AnyMotionDetector {
if (mMeasurementInProgress) {
mSensorManager.unregisterListener(mListener);
mHandler.removeCallbacks(mMeasurementTimeout);
- mWakeLock.release();
long detectionEndTime = SystemClock.elapsedRealtime();
mMeasurementInProgress = false;
mPreviousGravityVector = mCurrentGravityVector;
@@ -196,8 +203,10 @@ public class AnyMotionDetector {
status = getStationaryStatus();
if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
if (status != RESULT_UNKNOWN) {
- if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " +
- status);
+ mWakeLock.release();
+ if (DEBUG) {
+ Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " + status);
+ }
mState = STATE_INACTIVE;
} else {
/*
@@ -275,7 +284,7 @@ public class AnyMotionDetector {
@Override
public void run() {
synchronized (mLock) {
- startOrientationMeasurement();
+ startOrientationMeasurementLocked();
}
}
};
@@ -442,4 +451,4 @@ public class AnyMotionDetector {
return msg;
}
}
-} \ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index c38a89e30807..0a2153e9f31b 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -979,6 +979,7 @@ public class AppOpsService extends IAppOpsService.Stub {
usageRestrictions.put(usage, r);
}
}
+ notifyWatchersOfChange(code);
}
@Override
@@ -1046,7 +1047,9 @@ public class AppOpsService extends IAppOpsService.Stub {
op.duration = 0;
final int switchCode = AppOpsManager.opToSwitch(code);
UidState uidState = ops.uidState;
- if (uidState.opModes != null) {
+ // If there is a non-default per UID policy (we set UID op mode only if
+ // non-default) it takes over, otherwise use the per package policy.
+ if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
final int uidMode = uidState.opModes.get(switchCode);
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
@@ -1055,13 +1058,15 @@ public class AppOpsService extends IAppOpsService.Stub {
op.rejectTime = System.currentTimeMillis();
return uidMode;
}
- }
- final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
- if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
- + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
- op.rejectTime = System.currentTimeMillis();
- return switchOp.mode;
+ } else {
+ final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
+ if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+ if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+ + switchCode + " (" + code + ") uid " + uid + " package "
+ + packageName);
+ op.rejectTime = System.currentTimeMillis();
+ return switchOp.mode;
+ }
}
if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
+ " package " + packageName);
@@ -2280,6 +2285,10 @@ public class AppOpsService extends IAppOpsService.Stub {
pruneUserRestrictionsForToken(token, userHandle);
}
+ notifyWatchersOfChange(code);
+ }
+
+ private void notifyWatchersOfChange(int code) {
final ArrayList<Callback> clonedCallbacks;
synchronized (this) {
ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 95d3cc3bbcf0..82a36b4958a6 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -371,8 +371,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
private int mNetTransitionWakeLockTimeout;
private final PowerManager.WakeLock mPendingIntentWakeLock;
- private InetAddress mDefaultDns;
-
// used in DBG mode to track inet condition reports
private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
private ArrayList mInetLog;
@@ -645,19 +643,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
- // read our default dns server ip
- String dns = Settings.Global.getString(context.getContentResolver(),
- Settings.Global.DEFAULT_DNS_SERVER);
- if (dns == null || dns.length() == 0) {
- dns = context.getResources().getString(
- com.android.internal.R.string.config_default_dns_server);
- }
- try {
- mDefaultDns = NetworkUtils.numericToInetAddress(dns);
- } catch (IllegalArgumentException e) {
- loge("Error setting defaultDns using " + dns);
- }
-
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
@@ -4149,14 +4134,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// }
updateTcpBufferSizes(networkAgent);
- // TODO: deprecate and remove mDefaultDns when we can do so safely. See http://b/18327075
- // In L, we used it only when the network had Internet access but provided no DNS servers.
- // For now, just disable it, and if disabling it doesn't break things, remove it.
- // final boolean useDefaultDns = networkAgent.networkCapabilities.hasCapability(
- // NET_CAPABILITY_INTERNET);
- final boolean useDefaultDns = false;
- final boolean flushDns = updateRoutes(newLp, oldLp, netId);
- updateDnses(newLp, oldLp, netId, flushDns, useDefaultDns);
+ updateRoutes(newLp, oldLp, netId);
+ updateDnses(newLp, oldLp, netId);
updateClat(newLp, oldLp, networkAgent);
if (isDefaultNetwork(networkAgent)) {
@@ -4259,37 +4238,24 @@ public class ConnectivityService extends IConnectivityManager.Stub
return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
}
- private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId,
- boolean flush, boolean useDefaultDns) {
- if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
- Collection<InetAddress> dnses = newLp.getDnsServers();
- if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) {
- dnses = new ArrayList();
- dnses.add(mDefaultDns);
- if (DBG) {
- loge("no dns provided for netId " + netId + ", so using defaults");
- }
- }
- if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
- try {
- mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses),
- newLp.getDomains());
- } catch (Exception e) {
- loge("Exception in setDnsServersForNetwork: " + e);
- }
- final NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null && defaultNai.network.netId == netId) {
- setDefaultDnsSystemProperties(dnses);
- }
- flushVmDnsCache();
- } else if (flush) {
- try {
- mNetd.flushNetworkDnsCache(netId);
- } catch (Exception e) {
- loge("Exception in flushNetworkDnsCache: " + e);
- }
- flushVmDnsCache();
+ private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
+ if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
+ return; // no updating necessary
+ }
+
+ Collection<InetAddress> dnses = newLp.getDnsServers();
+ if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
+ try {
+ mNetd.setDnsServersForNetwork(
+ netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
+ } catch (Exception e) {
+ loge("Exception in setDnsServersForNetwork: " + e);
+ }
+ final NetworkAgentInfo defaultNai = getDefaultNetwork();
+ if (defaultNai != null && defaultNai.network.netId == netId) {
+ setDefaultDnsSystemProperties(dnses);
}
+ flushVmDnsCache();
}
private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 423f9456ee7f..ccb4647d8591 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -198,6 +198,7 @@ public class DeviceIdleController extends SystemService
private long mNextIdleDelay;
private long mNextLightIdleDelay;
private long mNextLightAlarmTime;
+ private long mNextSensingTimeoutAlarmTime;
private long mCurIdleBudget;
private long mMaintenanceStartTime;
@@ -339,6 +340,18 @@ public class DeviceIdleController extends SystemService
}
};
+ private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
+ = new AlarmManager.OnAlarmListener() {
+ @Override
+ public void onAlarm() {
+ if (mState == STATE_SENSING) {
+ synchronized (DeviceIdleController.this) {
+ becomeInactiveIfAppropriateLocked();
+ }
+ }
+ }
+ };
+
private final AlarmManager.OnAlarmListener mDeepAlarmListener
= new AlarmManager.OnAlarmListener() {
@Override
@@ -924,6 +937,11 @@ public class DeviceIdleController extends SystemService
@Override
public void onAnyMotionResult(int result) {
if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
+ if (result != AnyMotionDetector.RESULT_UNKNOWN) {
+ synchronized (this) {
+ cancelSensingTimeoutAlarmLocked();
+ }
+ }
if (result == AnyMotionDetector.RESULT_MOVED) {
if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
synchronized (this) {
@@ -1746,6 +1764,7 @@ public class DeviceIdleController extends SystemService
mNextIdleDelay = 0;
mNextLightIdleDelay = 0;
cancelAlarmLocked();
+ cancelSensingTimeoutAlarmLocked();
cancelLocatingLocked();
stopMonitoringMotionLocked();
mAnyMotionDetector.stop();
@@ -1866,15 +1885,16 @@ public class DeviceIdleController extends SystemService
mState = STATE_SENSING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
EventLogTags.writeDeviceIdle(mState, reason);
- scheduleAlarmLocked(mConstants.SENSING_TIMEOUT, false);
+ scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
cancelLocatingLocked();
- mAnyMotionDetector.checkForAnyMotion();
mNotMoving = false;
mLocated = false;
mLastGenericLocation = null;
mLastGpsLocation = null;
+ mAnyMotionDetector.checkForAnyMotion();
break;
case STATE_SENSING:
+ cancelSensingTimeoutAlarmLocked();
mState = STATE_LOCATING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
EventLogTags.writeDeviceIdle(mState, reason);
@@ -2161,6 +2181,13 @@ public class DeviceIdleController extends SystemService
}
}
+ void cancelSensingTimeoutAlarmLocked() {
+ if (mNextSensingTimeoutAlarmTime != 0) {
+ mNextSensingTimeoutAlarmTime = 0;
+ mAlarmManager.cancel(mSensingTimeoutAlarmListener);
+ }
+ }
+
void scheduleAlarmLocked(long delay, boolean idleUntil) {
if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
if (mMotionSensor == null) {
@@ -2194,6 +2221,13 @@ public class DeviceIdleController extends SystemService
mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
}
+ void scheduleSensingTimeoutAlarmLocked(long delay) {
+ if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
+ mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
+ "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
+ }
+
private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
outAppIds.clear();
diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java
index aa0a80508d0f..9ef02598c1d3 100644
--- a/services/core/java/com/android/server/DisplayThread.java
+++ b/services/core/java/com/android/server/DisplayThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton foreground thread for the system. This is a thread for
@@ -36,6 +37,7 @@ public final class DisplayThread extends ServiceThread {
if (sInstance == null) {
sInstance = new DisplayThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java
index 03765db35bae..5f85cbac21d5 100644
--- a/services/core/java/com/android/server/FgThread.java
+++ b/services/core/java/com/android/server/FgThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton foreground thread for the system. This is a thread for regular
@@ -38,6 +39,7 @@ public final class FgThread extends ServiceThread {
if (sInstance == null) {
sInstance = new FgThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index d6575e84352d..aa986489e1c2 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -34,6 +34,7 @@ import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
+import android.util.MutableBoolean;
import android.util.Slog;
import android.view.KeyEvent;
@@ -251,7 +252,8 @@ public class GestureLauncherService extends SystemService {
return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources);
}
- public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
+ public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
+ MutableBoolean outLaunched) {
boolean launched = false;
boolean intercept = false;
long doubleTapInterval;
@@ -276,6 +278,7 @@ public class GestureLauncherService extends SystemService {
}
}
MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval);
+ outLaunched.value = launched;
return intercept && launched;
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index b8cbf16e9f6f..ac7872a94bf8 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -15,6 +15,8 @@
package com.android.server;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import com.android.internal.content.PackageMonitor;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
@@ -37,6 +39,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -125,6 +128,7 @@ import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.Switch;
import android.widget.TextView;
+import android.widget.Toast;
import java.io.File;
import java.io.FileDescriptor;
@@ -132,6 +136,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
@@ -177,6 +182,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
+ @Retention(SOURCE)
+ @IntDef({HardKeyboardBehavior.WIRELESS_AFFORDANCE, HardKeyboardBehavior.WIRED_AFFORDANCE})
+ private @interface HardKeyboardBehavior {
+ int WIRELESS_AFFORDANCE = 0;
+ int WIRED_AFFORDANCE = 1;
+ }
final Context mContext;
final Resources mRes;
@@ -452,6 +463,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private AlertDialog.Builder mDialogBuilder;
private AlertDialog mSwitchingDialog;
private View mSwitchingDialogTitleView;
+ private Toast mSubtypeSwitchedByShortCutToast;
private InputMethodInfo[] mIms;
private int[] mSubtypeIds;
private LocaleList mLastSystemLocales;
@@ -460,6 +472,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
private final IPackageManager mIPackageManager;
private final String mSlotIme;
+ @HardKeyboardBehavior
+ private final int mHardKeyboardBehavior;
class SettingsObserver extends ContentObserver {
int mUserId;
@@ -852,6 +866,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mHasFeature = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_INPUT_METHODS);
mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime);
+ mHardKeyboardBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_externalHardKeyboardBehavior);
Bundle extras = new Bundle();
extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
@@ -1710,11 +1726,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (isScreenLocked()) return false;
if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false;
if (mWindowManagerInternal.isHardKeyboardAvailable()) {
- // When physical keyboard is attached, we show the ime switcher (or notification if
- // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
- // exists in the IME switcher dialog. Might be OK to remove this condition once
- // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live.
- return true;
+ if (mHardKeyboardBehavior == HardKeyboardBehavior.WIRELESS_AFFORDANCE) {
+ // When physical keyboard is attached, we show the ime switcher (or notification if
+ // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
+ // exists in the IME switcher dialog. Might be OK to remove this condition once
+ // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live.
+ return true;
+ }
} else if ((visibility & InputMethodService.IME_VISIBLE) == 0) {
return false;
}
@@ -2952,6 +2970,27 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return;
}
setInputMethodLocked(nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
+ if (mSubtypeSwitchedByShortCutToast != null) {
+ mSubtypeSwitchedByShortCutToast.cancel();
+ mSubtypeSwitchedByShortCutToast = null;
+ }
+ if ((mImeWindowVis & InputMethodService.IME_VISIBLE) != 0) {
+ // IME window is shown. The user should be able to visually understand that the
+ // subtype is changed in most of cases. To avoid UI overlap, we do not show a toast
+ // in this case.
+ return;
+ }
+ final InputMethodInfo newInputMethodInfo = mMethodMap.get(mCurMethodId);
+ if (newInputMethodInfo == null) {
+ return;
+ }
+ final CharSequence toastText = InputMethodUtils.getImeAndSubtypeDisplayName(mContext,
+ newInputMethodInfo, mCurrentSubtype);
+ if (!TextUtils.isEmpty(toastText)) {
+ mSubtypeSwitchedByShortCutToast = Toast.makeText(mContext, toastText.toString(),
+ Toast.LENGTH_SHORT);
+ mSubtypeSwitchedByShortCutToast.show();
+ }
}
}
@@ -3823,6 +3862,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ private static String imeWindowStatusToString(final int imeWindowVis) {
+ final StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ if ((imeWindowVis & InputMethodService.IME_ACTIVE) != 0) {
+ sb.append("Active");
+ first = false;
+ }
+ if ((imeWindowVis & InputMethodService.IME_VISIBLE) != 0) {
+ if (!first) {
+ sb.append("|");
+ }
+ sb.append("Visible");
+ }
+ return sb.toString();
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -3870,6 +3925,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
method = mCurMethod;
p.println(" mCurMethod=" + mCurMethod);
p.println(" mEnabledSession=" + mEnabledSession);
+ p.println(" mImeWindowVis=" + imeWindowStatusToString(mImeWindowVis));
p.println(" mShowRequested=" + mShowRequested
+ " mShowExplicitlyRequested=" + mShowExplicitlyRequested
+ " mShowForced=" + mShowForced
diff --git a/services/core/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java
index 0f29857db345..ad4c19485f26 100644
--- a/services/core/java/com/android/server/IoThread.java
+++ b/services/core/java/com/android/server/IoThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton I/O thread for the system. This is a thread for non-background
@@ -35,6 +36,7 @@ public final class IoThread extends ServiceThread {
if (sInstance == null) {
sInstance = new IoThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index ed16af51c7eb..4ac75cabca3b 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -56,6 +56,9 @@ import android.provider.Settings;
import android.provider.Settings.Secure;
import android.provider.Settings.SettingNotFoundException;
import android.security.KeyStore;
+import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.text.TextUtils;
@@ -68,15 +71,33 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.LockSettingsStorage.CredentialHash;
+import libcore.util.HexEncoding;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
/**
* Keeps the lock pattern/password data and related settings for each user.
* Used by LockPatternUtils. Needs to be a service because Settings app also needs
@@ -90,6 +111,12 @@ public class LockSettingsService extends ILockSettings.Stub {
private static final int FBE_ENCRYPTED_NOTIFICATION = 0;
private static final boolean DEBUG = false;
+ private static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
+ private static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
+ private static final int PROFILE_KEY_IV_SIZE = 12;
+ private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
+ private final Object mSeparateChallengeLock = new Object();
+
private final Context mContext;
private final LockSettingsStorage mStorage;
private final LockSettingsStrongAuth mStrongAuth;
@@ -125,6 +152,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void onStart() {
+ AndroidKeyStoreProvider.install();
mLockSettingsService = new LockSettingsService(getContext());
publishBinderService("lock_settings", mLockSettingsService);
}
@@ -149,6 +177,46 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
+ /**
+ * Tie managed profile to primary profile if it is in unified mode and not tied before.
+ *
+ * @param managedUserId Managed profile user Id
+ * @param managedUserPassword Managed profile original password (when it has separated lock).
+ * NULL when it does not have a separated lock before.
+ */
+ public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
+ if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
+ // Only for managed profile
+ if (!UserManager.get(mContext).getUserInfo(managedUserId).isManagedProfile()) {
+ return;
+ }
+ // Do not tie managed profile when work challenge is enabled
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
+ return;
+ }
+ // Do not tie managed profile to parent when it's done already
+ if (mStorage.hasChildProfileLock(managedUserId)) {
+ return;
+ }
+ // Do not tie it to parent when parent does not have a screen lock
+ final int parentId = mUserManager.getProfileParent(managedUserId).id;
+ if (!mStorage.hasPassword(parentId) && !mStorage.hasPattern(parentId)) {
+ if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
+ return;
+ }
+ if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
+ byte[] randomLockSeed = new byte[] {};
+ try {
+ randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
+ String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
+ setLockPasswordInternal(newPassword, managedUserPassword, managedUserId);
+ tieProfileLockToParent(managedUserId, newPassword);
+ } catch (NoSuchAlgorithmException | RemoteException e) {
+ Slog.e(TAG, "Fail to tie managed profile", e);
+ // Nothing client can do to fix this issue, so we do not throw exception out
+ }
+ }
+
public LockSettingsService(Context context) {
mContext = context;
mStrongAuth = new LockSettingsStrongAuth(context);
@@ -254,7 +322,7 @@ public class LockSettingsService extends ILockSettings.Stub {
com.android.internal.R.color.system_notification_accent_color))
.setContentTitle(title)
.setContentText(message)
- .setContentInfo(detail)
+ .setSubText(detail)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setContentIntent(intent)
.build();
@@ -271,6 +339,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
public void onUnlockUser(int userId) {
+ tieManagedProfileLockIfNecessary(userId, null);
hideEncryptionNotification(new UserHandle(userId));
// Now we have unlocked the parent user we should show notifications
@@ -294,8 +363,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// Notify keystore that a new user was added.
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
final KeyStore ks = KeyStore.getInstance();
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- final UserInfo parentInfo = um.getProfileParent(userHandle);
+ final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
final int parentHandle = parentInfo != null ? parentInfo.id : -1;
ks.onUserAdded(userHandle, parentHandle);
} else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
@@ -343,9 +411,8 @@ public class LockSettingsService extends ILockSettings.Stub {
// These Settings changed after multi-user was enabled, hence need to be moved per user.
if (getString("migrated_user_specific", null, 0) == null) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final ContentResolver cr = mContext.getContentResolver();
- List<UserInfo> users = um.getUsers();
+ List<UserInfo> users = mUserManager.getUsers();
for (int user = 0; user < users.size(); user++) {
// Migrate owner info
final int userId = users.get(user).id;
@@ -380,8 +447,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// Migrates biometric weak such that the fallback mechanism becomes the primary.
if (getString("migrated_biometric_weak", null, 0) == null) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- List<UserInfo> users = um.getUsers();
+ List<UserInfo> users = mUserManager.getUsers();
for (int i = 0; i < users.size(); i++) {
int userId = users.get(i).id;
long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
@@ -407,9 +473,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// user was present on the system, so if we're upgrading to M and there is more than one
// user we disable the flag to remain consistent.
if (getString("migrated_lockscreen_disabled", null, 0) == null) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-
- final List<UserInfo> users = um.getUsers();
+ final List<UserInfo> users = mUserManager.getUsers();
final int userCount = users.size();
int switchableUsers = 0;
for (int i = 0; i < userCount; i++) {
@@ -469,6 +533,27 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
+ public boolean getSeparateProfileChallengeEnabled(int userId) throws RemoteException {
+ synchronized (mSeparateChallengeLock) {
+ return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
+ }
+ }
+
+ @Override
+ public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
+ String managedUserPassword) throws RemoteException {
+ synchronized (mSeparateChallengeLock) {
+ setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
+ if (enabled) {
+ mStorage.removeChildProfileLock(userId);
+ removeKeystoreProfileKey(userId);
+ } else {
+ tieManagedProfileLockIfNecessary(userId, managedUserPassword);
+ }
+ }
+ }
+
+ @Override
public void setBoolean(String key, boolean value, int userId) throws RemoteException {
checkWritePermission(userId);
setStringUnchecked(key, userId, value ? "1" : "0");
@@ -536,61 +621,65 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public boolean havePassword(int userId) throws RemoteException {
// Do we need a permissions check here?
-
return mStorage.hasPassword(userId);
}
@Override
public boolean havePattern(int userId) throws RemoteException {
// Do we need a permissions check here?
-
return mStorage.hasPattern(userId);
}
private void setKeystorePassword(String password, int userHandle) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final KeyStore ks = KeyStore.getInstance();
-
- if (um.getUserInfo(userHandle).isManagedProfile()) {
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
- ks.onUserPasswordChanged(userHandle, password);
- } else {
- throw new RuntimeException("Can't set keystore password on a profile that "
- + "doesn't have a profile challenge.");
- }
- } else {
- final List<UserInfo> profiles = um.getProfiles(userHandle);
- for (UserInfo pi : profiles) {
- // Change password on the given user and all its profiles that don't have
- // their own profile challenge enabled.
- if (pi.id == userHandle || (pi.isManagedProfile()
- && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) {
- ks.onUserPasswordChanged(pi.id, password);
- }
- }
- }
+ ks.onUserPasswordChanged(userHandle, password);
}
private void unlockKeystore(String password, int userHandle) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+ if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
final KeyStore ks = KeyStore.getInstance();
+ ks.unlock(userHandle, password);
+ }
+
+ private String getDecryptedPasswordForTiedProfile(int userId)
+ throws KeyStoreException, UnrecoverableKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+ InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
+ CertificateException, IOException {
+ if (DEBUG) Slog.v(TAG, "Unlock keystore for child profile");
+ byte[] storedData = mStorage.readChildProfileLock(userId);
+ if (storedData == null) {
+ throw new FileNotFoundException("Child profile lock file not found");
+ }
+ byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE);
+ byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
+ storedData.length);
+ byte[] decryptionResult;
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ SecretKey decryptionKey = (SecretKey) keyStore.getKey(
+ PROFILE_KEY_NAME_DECRYPT + userId, null);
+
+ Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+ + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
+
+ cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
+ decryptionResult = cipher.doFinal(encryptedPassword);
+ return new String(decryptionResult, StandardCharsets.UTF_8);
+ }
- if (um.getUserInfo(userHandle).isManagedProfile()) {
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
- ks.unlock(userHandle, password);
+ private void unlockChildProfile(int profileHandle) throws RemoteException {
+ try {
+ doVerifyPassword(getDecryptedPasswordForTiedProfile(profileHandle), false,
+ 0 /* no challenge */, profileHandle);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ if (e instanceof FileNotFoundException) {
+ Slog.i(TAG, "Child profile key not found");
} else {
- throw new RuntimeException("Can't unlock a profile explicitly if it "
- + "doesn't have a profile challenge.");
- }
- } else {
- final List<UserInfo> profiles = um.getProfiles(userHandle);
- for (UserInfo pi : profiles) {
- // Unlock the given user and all its profiles that don't have
- // their own profile challenge enabled.
- if (pi.id == userHandle || (pi.isManagedProfile()
- && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) {
- ks.unlock(pi.id, password);
- }
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
}
}
}
@@ -627,6 +716,21 @@ public class LockSettingsService extends ILockSettings.Stub {
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
+ try {
+ if (!mUserManager.getUserInfo(userId).isManagedProfile()) {
+ final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ for (UserInfo pi : profiles) {
+ // Unlock managed profile with unified lock
+ if (pi.isManagedProfile()
+ && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
+ && mStorage.hasChildProfileLock(pi.id)) {
+ unlockChildProfile(pi.id);
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to unlock child profile", e);
+ }
}
private byte[] getCurrentHandle(int userId) {
@@ -661,10 +765,57 @@ public class LockSettingsService extends ILockSettings.Stub {
return currentHandle;
}
+ private void onUserLockChanged(int userId) throws RemoteException {
+ if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+ return;
+ }
+ final boolean isSecure = mStorage.hasPassword(userId) || mStorage.hasPattern(userId);
+ final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ final int size = profiles.size();
+ for (int i = 0; i < size; i++) {
+ final UserInfo profile = profiles.get(i);
+ if (profile.isManagedProfile()) {
+ final int managedUserId = profile.id;
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
+ continue;
+ }
+ if (isSecure) {
+ tieManagedProfileLockIfNecessary(managedUserId, null);
+ } else {
+ getGateKeeperService().clearSecureUserId(managedUserId);
+ mStorage.writePatternHash(null, managedUserId);
+ setKeystorePassword(null, managedUserId);
+ clearUserKeyProtection(managedUserId);
+ mStorage.removeChildProfileLock(managedUserId);
+ removeKeystoreProfileKey(managedUserId);
+ }
+ }
+ }
+ }
+
+ private boolean isManagedProfileWithUnifiedLock(int userId) {
+ return mUserManager.getUserInfo(userId).isManagedProfile()
+ && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
+ }
+
+ private boolean isManagedProfileWithSeparatedLock(int userId) {
+ return mUserManager.getUserInfo(userId).isManagedProfile()
+ && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
+ }
+ // This method should be called by LockPatternUtil only, all internal methods in this class
+ // should call setLockPatternInternal.
@Override
public void setLockPattern(String pattern, String savedCredential, int userId)
throws RemoteException {
+ synchronized (mSeparateChallengeLock) {
+ setLockPatternInternal(pattern, savedCredential, userId);
+ setSeparateProfileChallengeEnabled(userId, true, null);
+ }
+ }
+
+ public void setLockPatternInternal(String pattern, String savedCredential, int userId)
+ throws RemoteException {
byte[] currentHandle = getCurrentHandle(userId);
if (pattern == null) {
@@ -672,55 +823,157 @@ public class LockSettingsService extends ILockSettings.Stub {
mStorage.writePatternHash(null, userId);
setKeystorePassword(null, userId);
clearUserKeyProtection(userId);
+ onUserLockChanged(userId);
return;
}
- if (currentHandle == null) {
- if (savedCredential != null) {
- Slog.w(TAG, "Saved credential provided, but none stored");
+ if (isManagedProfileWithUnifiedLock(userId)) {
+ // get credential from keystore when managed profile has unified lock
+ try {
+ savedCredential = getDecryptedPasswordForTiedProfile(userId);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ if (e instanceof FileNotFoundException) {
+ Slog.i(TAG, "Child profile key not found");
+ } else {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ }
+ }
+ } else {
+ if (currentHandle == null) {
+ if (savedCredential != null) {
+ Slog.w(TAG, "Saved credential provided, but none stored");
+ }
+ savedCredential = null;
}
- savedCredential = null;
}
byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, pattern, userId);
if (enrolledHandle != null) {
mStorage.writePatternHash(enrolledHandle, userId);
setUserKeyProtection(userId, pattern, verifyPattern(pattern, 0, userId));
+ onUserLockChanged(userId);
} else {
throw new RemoteException("Failed to enroll pattern");
}
}
-
+ // This method should be called by LockPatternUtil only, all internal methods in this class
+ // should call setLockPasswordInternal.
@Override
public void setLockPassword(String password, String savedCredential, int userId)
throws RemoteException {
- byte[] currentHandle = getCurrentHandle(userId);
+ synchronized (mSeparateChallengeLock) {
+ setLockPasswordInternal(password, savedCredential, userId);
+ setSeparateProfileChallengeEnabled(userId, true, null);
+ }
+ }
+ public void setLockPasswordInternal(String password, String savedCredential, int userId)
+ throws RemoteException {
+ byte[] currentHandle = getCurrentHandle(userId);
if (password == null) {
getGateKeeperService().clearSecureUserId(userId);
mStorage.writePasswordHash(null, userId);
setKeystorePassword(null, userId);
clearUserKeyProtection(userId);
+ onUserLockChanged(userId);
return;
}
- if (currentHandle == null) {
- if (savedCredential != null) {
- Slog.w(TAG, "Saved credential provided, but none stored");
+ if (isManagedProfileWithUnifiedLock(userId)) {
+ // get credential from keystore when managed profile has unified lock
+ try {
+ savedCredential = getDecryptedPasswordForTiedProfile(userId);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ if (e instanceof FileNotFoundException) {
+ Slog.i(TAG, "Child profile key not found");
+ } else {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ }
+ }
+ } else {
+ if (currentHandle == null) {
+ if (savedCredential != null) {
+ Slog.w(TAG, "Saved credential provided, but none stored");
+ }
+ savedCredential = null;
}
- savedCredential = null;
}
byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, password, userId);
if (enrolledHandle != null) {
mStorage.writePasswordHash(enrolledHandle, userId);
setUserKeyProtection(userId, password, verifyPassword(password, 0, userId));
+ onUserLockChanged(userId);
} else {
throw new RemoteException("Failed to enroll password");
}
}
+ private void tieProfileLockToParent(int userId, String password) {
+ if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
+ byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
+ byte[] encryptionResult;
+ byte[] iv;
+ try {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
+ keyGenerator.init(new SecureRandom());
+ SecretKey secretKey = keyGenerator.generateKey();
+
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ keyStore.setEntry(
+ PROFILE_KEY_NAME_ENCRYPT + userId,
+ new java.security.KeyStore.SecretKeyEntry(secretKey),
+ new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ keyStore.setEntry(
+ PROFILE_KEY_NAME_DECRYPT + userId,
+ new java.security.KeyStore.SecretKeyEntry(secretKey),
+ new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .setUserAuthenticationRequired(true)
+ .setUserAuthenticationValidityDurationSeconds(30)
+ .build());
+
+ // Key imported, obtain a reference to it.
+ SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
+ PROFILE_KEY_NAME_ENCRYPT + userId, null);
+ // The original key can now be discarded.
+
+ Cipher cipher = Cipher.getInstance(
+ KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
+ + KeyProperties.ENCRYPTION_PADDING_NONE);
+ cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
+ encryptionResult = cipher.doFinal(randomLockSeed);
+ iv = cipher.getIV();
+ } catch (CertificateException | UnrecoverableKeyException
+ | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
+ | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new RuntimeException("Failed to encrypt key", e);
+ }
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ try {
+ if (iv.length != PROFILE_KEY_IV_SIZE) {
+ throw new RuntimeException("Invalid iv length: " + iv.length);
+ }
+ outputStream.write(iv);
+ outputStream.write(encryptionResult);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to concatenate byte arrays", e);
+ }
+ mStorage.writeChildProfileLock(userId, outputStream.toByteArray());
+ }
+
private byte[] enrollCredential(byte[] enrolledHandle,
String enrolledCredential, String toEnroll, int userId)
throws RemoteException {
@@ -820,7 +1073,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void setCredential(String pattern, String oldPattern, int userId)
throws RemoteException {
- setLockPattern(pattern, oldPattern, userId);
+ setLockPatternInternal(pattern, oldPattern, userId);
}
@Override
@@ -838,7 +1091,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK
&& shouldReEnrollBaseZero) {
- setLockPattern(pattern, patternToVerify, userId);
+ setLockPatternInternal(pattern, patternToVerify, userId);
}
return response;
@@ -857,6 +1110,37 @@ public class LockSettingsService extends ILockSettings.Stub {
return doVerifyPassword(password, true, challenge, userId);
}
+ @Override
+ public VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern,
+ long challenge, int userId) throws RemoteException {
+ checkPasswordReadPermission(userId);
+ if (!isManagedProfileWithUnifiedLock(userId)) {
+ throw new RemoteException("User id must be managed profile with unified lock");
+ }
+ final int parentProfileId = mUserManager.getProfileParent(userId).id;
+ // Unlock parent by using parent's challenge
+ final VerifyCredentialResponse parentResponse = isPattern
+ ? doVerifyPattern(password, true, challenge, parentProfileId)
+ : doVerifyPassword(password, true, challenge, parentProfileId);
+ if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
+ // Failed, just return parent's response
+ return parentResponse;
+ }
+
+ try {
+ // Unlock work profile, and work profile with unified lock must use password only
+ return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true,
+ challenge,
+ userId);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ throw new RemoteException("Unable to get tied profile token");
+ }
+ }
+
private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge,
long challenge, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
@@ -866,7 +1150,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void setCredential(String password, String oldPassword, int userId)
throws RemoteException {
- setLockPassword(password, oldPassword, userId);
+ setLockPasswordInternal(password, oldPassword, userId);
}
@Override
@@ -947,8 +1231,7 @@ public class LockSettingsService extends ILockSettings.Stub {
" with token length " + response.getPayload().length);
unlockUser(userId, response.getPayload(), secretFromCredential(credential));
- UserInfo info = UserManager.get(mContext).getUserInfo(userId);
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ if (isManagedProfileWithSeparatedLock(userId)) {
TrustManager trustManager =
(TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
trustManager.setDeviceLockedForUser(userId, false);
@@ -1027,6 +1310,23 @@ public class LockSettingsService extends ILockSettings.Stub {
} catch (RemoteException ex) {
Slog.w(TAG, "unable to clear GK secure user id");
}
+ if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+ removeKeystoreProfileKey(userId);
+ }
+ }
+
+ private void removeKeystoreProfileKey(int targetUserId) {
+ if (DEBUG) Slog.v(TAG, "Remove keystore profile key for user: " + targetUserId);
+ try {
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ keyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
+ keyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
+ } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
+ | IOException e) {
+ // We have tried our best to remove all keys
+ Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index 816c791d47fa..d136f1af7654 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -17,7 +17,6 @@
package com.android.server;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.widget.LockPatternUtils;
import android.content.ContentValues;
import android.content.Context;
@@ -30,6 +29,7 @@ import android.os.UserManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import java.io.File;
import java.io.IOException;
@@ -44,6 +44,7 @@ class LockSettingsStorage {
private static final String TAG = "LockSettingsStorage";
private static final String TABLE = "locksettings";
+ private static final boolean DEBUG = false;
private static final String COLUMN_KEY = "name";
private static final String COLUMN_USERID = "user";
@@ -62,6 +63,7 @@ class LockSettingsStorage {
private static final String LEGACY_LOCK_PATTERN_FILE = "gesture.key";
private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key";
private static final String LEGACY_LOCK_PASSWORD_FILE = "password.key";
+ private static final String CHILD_PROFILE_LOCK_FILE = "gatekeeper.profile.key";
private static final Object DEFAULT = new Object();
@@ -70,8 +72,7 @@ class LockSettingsStorage {
private final Cache mCache = new Cache();
private final Object mFileWriteLock = new Object();
- private int mStoredCredentialType;
- private LockPatternUtils mLockPatternUtils;
+ private SparseArray<Integer> mStoredCredentialType;
class CredentialHash {
static final int TYPE_NONE = -1;
@@ -101,7 +102,7 @@ class LockSettingsStorage {
public LockSettingsStorage(Context context, Callback callback) {
mContext = context;
mOpenHelper = new DatabaseHelper(context, callback);
- mLockPatternUtils = new LockPatternUtils(context);
+ mStoredCredentialType = new SparseArray<Integer>();
}
public void writeKeyValue(String key, String value, int userId) {
@@ -182,32 +183,34 @@ class LockSettingsStorage {
}
public int getStoredCredentialType(int userId) {
- if (mStoredCredentialType != 0) {
- return mStoredCredentialType;
+ final Integer cachedStoredCredentialType = mStoredCredentialType.get(userId);
+ if (cachedStoredCredentialType != null) {
+ return cachedStoredCredentialType.intValue();
}
+ int storedCredentialType;
CredentialHash pattern = readPatternHash(userId);
if (pattern == null) {
if (readPasswordHash(userId) != null) {
- mStoredCredentialType = CredentialHash.TYPE_PASSWORD;
+ storedCredentialType = CredentialHash.TYPE_PASSWORD;
} else {
- mStoredCredentialType = CredentialHash.TYPE_NONE;
+ storedCredentialType = CredentialHash.TYPE_NONE;
}
} else {
CredentialHash password = readPasswordHash(userId);
if (password != null) {
// Both will never be GateKeeper
if (password.version == CredentialHash.VERSION_GATEKEEPER) {
- mStoredCredentialType = CredentialHash.TYPE_PASSWORD;
+ storedCredentialType = CredentialHash.TYPE_PASSWORD;
} else {
- mStoredCredentialType = CredentialHash.TYPE_PATTERN;
+ storedCredentialType = CredentialHash.TYPE_PATTERN;
}
} else {
- mStoredCredentialType = CredentialHash.TYPE_PATTERN;
+ storedCredentialType = CredentialHash.TYPE_PATTERN;
}
}
-
- return mStoredCredentialType;
+ mStoredCredentialType.put(userId, storedCredentialType);
+ return storedCredentialType;
}
@@ -244,6 +247,27 @@ class LockSettingsStorage {
return null;
}
+ public void removeChildProfileLock(int userId) {
+ if (DEBUG)
+ Slog.e(TAG, "Remove child profile lock for user: " + userId);
+ try {
+ deleteFile(getChildProfileLockFile(userId));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void writeChildProfileLock(int userId, byte[] lock) {
+ writeFile(getChildProfileLockFile(userId), lock);
+ }
+
+ public byte[] readChildProfileLock(int userId) {
+ return readFile(getChildProfileLockFile(userId));
+ }
+
+ public boolean hasChildProfileLock(int userId) {
+ return hasFile(getChildProfileLockFile(userId));
+ }
public boolean hasPassword(int userId) {
return hasFile(getLockPasswordFilename(userId)) ||
@@ -321,16 +345,19 @@ class LockSettingsStorage {
}
private void deleteFile(String name) {
- File f = new File(name);
- if (f != null) {
- f.delete();
+ if (DEBUG) Slog.e(TAG, "Delete file " + name);
+ synchronized (mFileWriteLock) {
+ File file = new File(name);
+ if (file.exists()) {
+ file.delete();
+ mCache.putFile(name, null);
+ }
}
}
public void writePatternHash(byte[] hash, int userId) {
- mStoredCredentialType = hash == null
- ? CredentialHash.TYPE_NONE
- : CredentialHash.TYPE_PATTERN;
+ mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
+ : CredentialHash.TYPE_PATTERN);
writeFile(getLockPatternFilename(userId), hash);
clearPasswordHash(userId);
}
@@ -340,9 +367,8 @@ class LockSettingsStorage {
}
public void writePasswordHash(byte[] hash, int userId) {
- mStoredCredentialType = hash == null
- ? CredentialHash.TYPE_NONE
- : CredentialHash.TYPE_PASSWORD;
+ mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
+ : CredentialHash.TYPE_PASSWORD);
writeFile(getLockPasswordFilename(userId), hash);
clearPatternHash(userId);
}
@@ -375,8 +401,11 @@ class LockSettingsStorage {
return getLockCredentialFilePathForUser(userId, BASE_ZERO_LOCK_PATTERN_FILE);
}
+ private String getChildProfileLockFile(int userId) {
+ return getLockCredentialFilePathForUser(userId, CHILD_PROFILE_LOCK_FILE);
+ }
+
private String getLockCredentialFilePathForUser(int userId, String basename) {
- userId = getUserParentOrSelfId(userId);
String dataSystemDirectory =
android.os.Environment.getDataDirectory().getAbsolutePath() +
SYSTEM_DIRECTORY;
@@ -388,23 +417,6 @@ class LockSettingsStorage {
}
}
- private int getUserParentOrSelfId(int userId) {
- // Device supports per user encryption, so lock is applied to the given user.
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
- return userId;
- }
- // Device uses Block Based Encryption, and the parent user's lock is used for the whole
- // device.
- if (userId != 0) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- final UserInfo pi = um.getProfileParent(userId);
- if (pi != null) {
- return pi.id;
- }
- }
- return userId;
- }
-
public void removeUser(int userId) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -427,6 +439,9 @@ class LockSettingsStorage {
mCache.putFile(name, null);
}
}
+ } else {
+ // Manged profile
+ removeChildProfileLock(userId);
}
try {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index c6d536ddf671..bf4df94e92e2 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1937,16 +1937,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
@Override
- public void flushNetworkDnsCache(int netId) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- try {
- mConnector.execute("resolver", "flushnet", netId);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- }
- }
-
- @Override
public void setFirewallEnabled(boolean enabled) {
enforceSystemUid();
try {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 879bb6f72895..2a78f908649b 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -18,10 +18,12 @@ package com.android.server;
import android.Manifest.permission;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
@@ -30,6 +32,7 @@ import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.ScoredNetwork;
import android.os.Binder;
+import android.os.IBinder;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -55,17 +58,17 @@ import java.util.Set;
*/
public class NetworkScoreService extends INetworkScoreService.Stub {
private static final String TAG = "NetworkScoreService";
+ private static final boolean DBG = false;
private final Context mContext;
-
private final Map<Integer, INetworkScoreCache> mScoreCaches;
-
/** Lock used to update mReceiver when scorer package changes occur. */
- private Object mReceiverLock = new Object[0];
+ private final Object mReceiverLock = new Object[0];
/** Clears scores when the active scorer package is no longer valid. */
@GuardedBy("mReceiverLock")
private ScorerChangedReceiver mReceiver;
+ private ScoringServiceConnection mServiceConnection;
private class ScorerChangedReceiver extends BroadcastReceiver {
final String mRegisteredPackage;
@@ -77,14 +80,23 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if ((Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
- Intent.ACTION_PACKAGE_REPLACED.equals(action) ||
- Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) &&
- NetworkScorerAppManager.getActiveScorer(mContext) == null) {
- // Package change has invalidated a scorer.
- Log.i(TAG, "Package " + mRegisteredPackage +
- " is no longer valid, disabling scoring");
- setScorerInternal(null);
+ if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+ || Intent.ACTION_PACKAGE_REPLACED.equals(action)
+ || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
+ NetworkScorerAppData activeScorer =
+ NetworkScorerAppManager.getActiveScorer(mContext);
+ if (activeScorer == null) {
+ // Package change has invalidated a scorer.
+ Log.i(TAG, "Package " + mRegisteredPackage +
+ " is no longer valid, disabling scoring.");
+ setScorerInternal(null);
+ } else if (activeScorer.mScoringServiceClassName == null) {
+ // The scoring service is not available, make sure it's unbound.
+ unbindFromScoringServiceIfNeeded();
+ } else {
+ // The scoring service may have changed or been added.
+ bindToScoringServiceIfNeeded(activeScorer);
+ }
}
}
}
@@ -96,6 +108,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
/** Called when the system is ready to run third-party code but before it actually does so. */
void systemReady() {
+ if (DBG) Log.d(TAG, "systemReady");
ContentResolver cr = mContext.getContentResolver();
if (Settings.Global.getInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 0) == 0) {
// On first run, we try to initialize the scorer to the one configured at build time.
@@ -111,7 +124,14 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
registerPackageReceiverIfNeeded();
}
+ /** Called when the system is ready for us to start third-party code. */
+ void systemRunning() {
+ if (DBG) Log.d(TAG, "systemRunning");
+ bindToScoringServiceIfNeeded();
+ }
+
private void registerPackageReceiverIfNeeded() {
+ if (DBG) Log.d(TAG, "registerPackageReceiverIfNeeded");
NetworkScorerAppData scorer = NetworkScorerAppManager.getActiveScorer(mContext);
synchronized (mReceiverLock) {
// Unregister the receiver if the current scorer has changed since last registration.
@@ -142,6 +162,41 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
}
}
+ private void bindToScoringServiceIfNeeded() {
+ if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded");
+ NetworkScorerAppData scorerData = NetworkScorerAppManager.getActiveScorer(mContext);
+ bindToScoringServiceIfNeeded(scorerData);
+ }
+
+ private void bindToScoringServiceIfNeeded(NetworkScorerAppData scorerData) {
+ if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + scorerData + ")");
+ if (scorerData != null && scorerData.mScoringServiceClassName != null) {
+ ComponentName componentName =
+ new ComponentName(scorerData.mPackageName, scorerData.mScoringServiceClassName);
+ // If we're connected to a different component then drop it.
+ if (mServiceConnection != null
+ && !mServiceConnection.mComponentName.equals(componentName)) {
+ unbindFromScoringServiceIfNeeded();
+ }
+
+ // If we're not connected at all then create a new connection.
+ if (mServiceConnection == null) {
+ mServiceConnection = new ScoringServiceConnection(componentName);
+ }
+
+ // Make sure the connection is connected (idempotent)
+ mServiceConnection.connect(mContext);
+ }
+ }
+
+ private void unbindFromScoringServiceIfNeeded() {
+ if (DBG) Log.d(TAG, "unbindFromScoringServiceIfNeeded");
+ if (mServiceConnection != null) {
+ mServiceConnection.disconnect(mContext);
+ }
+ mServiceConnection = null;
+ }
+
@Override
public boolean updateScores(ScoredNetwork[] networks) {
if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) {
@@ -228,8 +283,10 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
/** Set the active scorer. Callers are responsible for checking permissions as appropriate. */
private boolean setScorerInternal(String packageName) {
+ if (DBG) Log.d(TAG, "setScorerInternal(" + packageName + ")");
long token = Binder.clearCallingIdentity();
try {
+ unbindFromScoringServiceIfNeeded();
// Preemptively clear scores even though the set operation could fail. We do this for
// safety as scores should never be compared across apps; in practice, Settings should
// only be allowing valid apps to be set as scorers, so failure here should be rare.
@@ -237,8 +294,13 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
// Get the scorer that is about to be replaced, if any, so we can notify it directly.
NetworkScorerAppData prevScorer = NetworkScorerAppManager.getActiveScorer(mContext);
boolean result = NetworkScorerAppManager.setActiveScorer(mContext, packageName);
+ // Unconditionally attempt to bind to the current scorer. If setActiveScorer() failed
+ // then we'll attempt to restore the previous binding (if any), otherwise an attempt
+ // will be made to bind to the new scorer.
+ bindToScoringServiceIfNeeded();
if (result) { // new scorer successfully set
registerPackageReceiverIfNeeded();
+
Intent intent = new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED);
if (prevScorer != null) { // Directly notify the old scorer.
intent.setPackage(prevScorer.mPackageName);
@@ -295,7 +357,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
return;
}
writer.println("Current scorer: " + currentScorer.mPackageName);
- writer.flush();
for (INetworkScoreCache scoreCache : getScoreCaches()) {
try {
@@ -307,6 +368,12 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
}
}
}
+ if (mServiceConnection != null) {
+ mServiceConnection.dump(fd, writer, args);
+ } else {
+ writer.println("ScoringServiceConnection: null");
+ }
+ writer.flush();
}
/**
@@ -320,4 +387,50 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
return new HashSet<>(mScoreCaches.values());
}
}
+
+ private static class ScoringServiceConnection implements ServiceConnection {
+ private final ComponentName mComponentName;
+ private boolean mBound = false;
+
+ ScoringServiceConnection(ComponentName componentName) {
+ mComponentName = componentName;
+ }
+
+ void connect(Context context) {
+ disconnect(context);
+ Intent service = new Intent();
+ service.setComponent(mComponentName);
+ mBound = context.bindServiceAsUser(service, this,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ UserHandle.SYSTEM);
+ if (!mBound) {
+ Log.w(TAG, "Bind call failed for " + service);
+ }
+ }
+
+ void disconnect(Context context) {
+ try {
+ if (mBound) {
+ mBound = false;
+ context.unbindService(this);
+ }
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Unbind failed.", e);
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DBG) Log.d(TAG, "ScoringServiceConnection, disconnected: " + name.flattenToString());
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java
index 0beb77fb4b92..c06afc2505ee 100644
--- a/services/core/java/com/android/server/UiThread.java
+++ b/services/core/java/com/android/server/UiThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton thread for showing UI. This is a foreground thread, and in
@@ -35,6 +36,7 @@ public final class UiThread extends ServiceThread {
if (sInstance == null) {
sInstance = new UiThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d741c4948280..5d1cb8a08280 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -343,6 +343,25 @@ public final class ActiveServices {
return null;
}
+ if (!r.startRequested) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Before going further -- if this app is not allowed to run in the
+ // background, then at this point we aren't going to let it period.
+ final int allowed = mAm.checkAllowBackgroundLocked(
+ r.appInfo.uid, r.packageName, callingPid, true);
+ if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
+ Slog.w(TAG, "Background start not allowed: service "
+ + service + " to " + r.name.flattenToShortString()
+ + " from pid=" + callingPid + " uid=" + callingUid
+ + " pkg=" + callingPackage);
+ return null;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
@@ -1274,23 +1293,6 @@ public final class ActiveServices {
}
r = smap.mServicesByName.get(name);
if (r == null && createIfNeeded) {
- final long token = Binder.clearCallingIdentity();
- try {
- // Before going further -- if this app is not allowed to run in the
- // background, then at this point we aren't going to let it period.
- final int allowed = mAm.checkAllowBackgroundLocked(
- sInfo.applicationInfo.uid, sInfo.packageName, callingPid, true);
- if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
- Slog.w(TAG, "Background execution not allowed: service "
- + service + " to " + name.flattenToShortString()
- + " from pid=" + callingPid + " uid=" + callingUid
- + " pkg=" + callingPackage);
- return null;
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
Intent.FilterComparison filter
= new Intent.FilterComparison(service.cloneFilter());
ServiceRestarter res = new ServiceRestarter();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 82332208a3cd..4852788af3d1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1105,19 +1105,19 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName mTopComponent;
String mTopAction = Intent.ACTION_MAIN;
String mTopData;
- boolean mProcessesReady = false;
- boolean mSystemReady = false;
- boolean mBooting = false;
- boolean mCallFinishBooting = false;
- boolean mBootAnimationComplete = false;
- boolean mOnBattery = false;
- boolean mLaunchWarningShown = false;
- Context mContext;
+ volatile boolean mProcessesReady = false;
+ volatile boolean mSystemReady = false;
+ volatile boolean mOnBattery = false;
+ volatile int mFactoryTest;
- int mFactoryTest;
+ @GuardedBy("this") boolean mBooting = false;
+ @GuardedBy("this") boolean mCallFinishBooting = false;
+ @GuardedBy("this") boolean mBootAnimationComplete = false;
+ @GuardedBy("this") boolean mLaunchWarningShown = false;
+ @GuardedBy("this") boolean mCheckedForSetup = false;
- boolean mCheckedForSetup;
+ Context mContext;
/**
* The time at which we will allow normal application switches again,
@@ -13227,10 +13227,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// Merge several logcat streams, and take the last N lines
InputStreamReader input = null;
try {
- java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
- "-v", "time", "-b", "events", "-b", "system", "-b", "main",
- "-b", "crash",
- "-t", String.valueOf(lines)).redirectErrorStream(true).start();
+ java.lang.Process logcat = new ProcessBuilder(
+ "/system/bin/timeout", "-k", "15s", "10s",
+ "/system/bin/logcat", "-v", "time", "-b", "events", "-b", "system",
+ "-b", "main", "-b", "crash", "-t", String.valueOf(lines))
+ .redirectErrorStream(true).start();
try { logcat.getOutputStream().close(); } catch (IOException e) {}
try { logcat.getErrorStream().close(); } catch (IOException e) {}
@@ -15456,8 +15457,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
- if (oomAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
- || oomIndex == (oomPss.length-1)) {
+ if (oomIndex == (oomPss.length - 1)
+ || (oomAdj >= DUMP_MEM_OOM_ADJ[oomIndex]
+ && oomAdj < DUMP_MEM_OOM_ADJ[oomIndex + 1])) {
oomPss[oomIndex] += myTotalPss;
oomSwapPss[oomIndex] += myTotalSwapPss;
if (oomProcs[oomIndex] == null) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 811b48fc4fe5..7b2a37081103 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1984,6 +1984,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
mTmpConfigs.clear();
mTmpInsetBounds.clear();
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
+ final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
for (int i = tasks.size() - 1; i >= 0; i--) {
final TaskRecord task = tasks.get(i);
if (task.isResizeable()) {
@@ -1995,9 +1997,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
fitWithinBounds(tempRect2, bounds);
task.updateOverrideConfiguration(tempRect2);
} else {
- task.updateOverrideConfiguration(
- tempTaskBounds != null ? tempTaskBounds : bounds,
- tempTaskInsetBounds != null ? tempTaskInsetBounds : bounds);
+ task.updateOverrideConfiguration(taskBounds, insetBounds);
}
}
@@ -2043,8 +2043,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
resizeStackUncheckedLocked(stack, dockedBounds, tempDockedTaskBounds,
tempDockedTaskInsetBounds);
- if (stack.mFullscreen) {
- // The dock stack went fullscreen which is kinda like dismissing it.
+ // TODO: Checking for isAttached might not be needed as if the user passes in null
+ // dockedBounds then they want the docked stack to be dismissed.
+ if (stack.mFullscreen || (dockedBounds == null && !stack.isAttached())) {
+ // The dock stack either was dismissed or went fullscreen, which is kinda the same.
// In this case we make all other static stacks fullscreen and move all
// docked stack tasks to the fullscreen stack.
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
@@ -2072,13 +2074,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
mWindowManager.getStackDockedModeBounds(
HOME_STACK_ID, tempRect, true /* ignoreVisibility */);
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
- if (StackId.isResizeableByDockedStack(i)) {
- ActivityStack otherStack = getStack(i);
- if (otherStack != null) {
- resizeStackLocked(i, tempRect, tempOtherTaskBounds,
- tempOtherTaskInsetBounds, preserveWindows,
- true /* allowResizeInDockedMode */);
- }
+ if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
+ resizeStackLocked(i, tempRect, tempOtherTaskBounds,
+ tempOtherTaskInsetBounds, preserveWindows,
+ true /* allowResizeInDockedMode */);
}
}
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 6cd756186ab7..68bd2fd3ce3e 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -724,9 +724,7 @@ class AppErrors {
final boolean crashSilenced = mAppsNotReportingCrashes != null &&
mAppsNotReportingCrashes.contains(proc.info.packageName);
if (mService.canShowErrorDialogs() && !crashSilenced) {
- Dialog d = new AppErrorDialog(mContext, mService, data);
- d.show();
- proc.crashDialog = d;
+ proc.crashDialog = new AppErrorDialog(mContext, mService, data);
} else {
// The device is asleep, so just pretend that the user
// saw a crash dialog and hit "force quit".
@@ -735,6 +733,10 @@ class AppErrors {
}
}
}
+ // If we've created a crash dialog, show it without the lock held
+ if(data.proc.crashDialog != null) {
+ data.proc.crashDialog.show();
+ }
}
void stopReportingCrashesLocked(ProcessRecord proc) {
@@ -924,6 +926,7 @@ class AppErrors {
}
void handleShowAnrUi(Message msg) {
+ Dialog d = null;
synchronized (mService) {
HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
ProcessRecord proc = (ProcessRecord)data.get("app");
@@ -944,10 +947,9 @@ class AppErrors {
null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
if (mService.canShowErrorDialogs()) {
- Dialog d = new AppNotRespondingDialog(mService,
+ d = new AppNotRespondingDialog(mService,
mContext, proc, (ActivityRecord)data.get("activity"),
msg.arg1 != 0);
- d.show();
proc.anrDialog = d;
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
@@ -956,6 +958,10 @@ class AppErrors {
mService.killAppAtUsersRequest(proc, null);
}
}
+ // If we've created a crash dialog, show it without the lock held
+ if (d != null) {
+ d.show();
+ }
}
/**
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index aef454ee6357..e0a142befd2d 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -237,7 +237,13 @@ final class UserController {
AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
- maybeUnlockUser(userId);
+ // We only attempt to unlock real users here; we delay unlocking
+ // profiles until after the parent user is unlocked.
+ if (getUserManager().isManagedProfile(userId)) {
+ Slog.d(TAG, "User " + userId + " is managed profile; delaying unlock attempt");
+ } else {
+ maybeUnlockUser(userId);
+ }
}
}
@@ -260,6 +266,9 @@ final class UserController {
mUserManager.onBeforeUnlockUser(userId);
progress.setProgress(20);
+ // Dispatch unlocked to system services
+ mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
+
// Send PRE_BOOT broadcasts if fingerprint changed
final UserInfo info = getUserInfo(userId);
if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {
@@ -302,9 +311,6 @@ final class UserController {
// Remember that we logged in
mUserManager.onUserLoggedIn(userId);
- // Dispatch unlocked to system services
- mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
-
// Dispatch unlocked to external apps
final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
@@ -905,6 +911,20 @@ final class UserController {
finishUserUnlocking(uss, progress);
}
+ // We just unlocked a user, so let's now attempt to unlock any managed
+ // profiles under that user.
+ synchronized (mService) {
+ for (int i = 0; i < mStartedUsers.size(); i++) {
+ final int testUserId = mStartedUsers.keyAt(i);
+ final UserInfo parent = getUserManager().getProfileParent(testUserId);
+ if (parent != null && parent.id == userId && testUserId != userId) {
+ Slog.d(TAG, "Found user " + testUserId + " with parent " + userId
+ + "; attempting unlock");
+ maybeUnlockUser(testUserId);
+ }
+ }
+ }
+
return true;
}
diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
index 7cac2270950d..f91db7813d42 100644
--- a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
+++ b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
@@ -18,18 +18,21 @@ package com.android.server.connectivity;
import com.android.server.SystemService;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.ConnectivityMetricsEvent;
import android.net.ConnectivityMetricsLogger;
import android.net.IConnectivityMetricsLogger;
-import android.net.IConnectivityMetricsLoggerSubscriber;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.ArrayMap;
+import android.os.Binder;
+import android.os.Parcel;
+import android.text.format.DateUtils;
import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.List;
/** {@hide} */
public class MetricsLoggerService extends SystemService {
@@ -43,134 +46,307 @@ public class MetricsLoggerService extends SystemService {
@Override
public void onStart() {
+ resetThrottlingCounters(System.currentTimeMillis());
}
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
- Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
+ if (DBG) Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
publishBinderService(ConnectivityMetricsLogger.CONNECTIVITY_METRICS_LOGGER_SERVICE,
mBinder);
}
}
- private final int MAX_NUMBER_OF_EVENTS = 100;
- private final int MAX_TIME_OFFSET = 15*60*1000; // 15 minutes
- private final List<ConnectivityMetricsEvent> mEvents = new ArrayList<>();
- private long mLastSentEventTimeMillis = System.currentTimeMillis();
+ // TODO: read from system property
+ private final int MAX_NUMBER_OF_EVENTS = 1000;
- private final void enforceConnectivityInternalPermission() {
+ // TODO: read from system property
+ private final int EVENTS_NOTIFICATION_THRESHOLD = 300;
+
+ // TODO: read from system property
+ private final int THROTTLING_TIME_INTERVAL_MILLIS = 60 * 60 * 1000; // 1 hour
+
+ // TODO: read from system property
+ private final int THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT = 1000;
+
+ private int mEventCounter = 0;
+
+ /**
+ * Reference of the last event in the list of cached events.
+ *
+ * When client of this service retrieves events by calling getEvents, it is passing
+ * ConnectivityMetricsEvent.Reference object. After getEvents returns, that object will
+ * contain this reference. The client can save it and use next time it calls getEvents.
+ * This way only new events will be returned.
+ */
+ private long mLastEventReference = 0;
+
+ private final int mThrottlingCounters[] =
+ new int[ConnectivityMetricsLogger.NUMBER_OF_COMPONENTS];
+
+ private long mThrottlingIntervalBoundaryMillis;
+
+ private final ArrayDeque<ConnectivityMetricsEvent> mEvents = new ArrayDeque<>();
+
+ private void enforceConnectivityInternalPermission() {
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.CONNECTIVITY_INTERNAL,
"MetricsLoggerService");
}
+ private void enforceDumpPermission() {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.DUMP,
+ "MetricsLoggerService");
+ }
+
+ private void resetThrottlingCounters(long currentTimeMillis) {
+ for (int i = 0; i < mThrottlingCounters.length; i++) {
+ mThrottlingCounters[i] = 0;
+ }
+ mThrottlingIntervalBoundaryMillis =
+ currentTimeMillis + THROTTLING_TIME_INTERVAL_MILLIS;
+ }
+
+ private void addEvent(ConnectivityMetricsEvent e) {
+ if (VDBG) {
+ Log.v(TAG, "writeEvent(" + e.toString() + ")");
+ }
+
+ while (mEvents.size() >= MAX_NUMBER_OF_EVENTS) {
+ mEvents.removeFirst();
+ }
+
+ mEvents.addLast(e);
+ }
+
/**
* Implementation of the IConnectivityMetricsLogger interface.
*/
private final IConnectivityMetricsLogger.Stub mBinder = new IConnectivityMetricsLogger.Stub() {
- private final ArrayMap<IConnectivityMetricsLoggerSubscriber,
- IBinder.DeathRecipient> mSubscribers = new ArrayMap<>();
-
-
- private ConnectivityMetricsEvent[] prepareEventsToSendIfReady() {
- ConnectivityMetricsEvent[] eventsToSend = null;
- final long currentTimeMillis = System.currentTimeMillis();
- final long timeOffset = currentTimeMillis - mLastSentEventTimeMillis;
- if (timeOffset >= MAX_TIME_OFFSET
- || timeOffset < 0 // system time has changed
- || mEvents.size() >= MAX_NUMBER_OF_EVENTS) {
- // batch events
- mLastSentEventTimeMillis = currentTimeMillis;
- eventsToSend = new ConnectivityMetricsEvent[mEvents.size()];
- mEvents.toArray(eventsToSend);
- mEvents.clear();
+ private final ArrayList<PendingIntent> mPendingIntents = new ArrayList<>();
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump ConnectivityMetricsLoggerService " +
+ "from from pid=" + Binder.getCallingPid() + ", uid=" +
+ Binder.getCallingUid());
+ return;
}
- return eventsToSend;
- }
- private void maybeSendEventsToSubscribers(ConnectivityMetricsEvent[] eventsToSend) {
- if (eventsToSend == null || eventsToSend.length == 0) return;
- synchronized (mSubscribers) {
- for (IConnectivityMetricsLoggerSubscriber s : mSubscribers.keySet()) {
- try {
- s.onEvents(eventsToSend);
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException " + ex);
+ boolean dumpSerializedSize = false;
+ boolean dumpEvents = false;
+ for (String arg : args) {
+ switch (arg) {
+ case "--events":
+ dumpEvents = true;
+ break;
+
+ case "--size":
+ dumpSerializedSize = true;
+ break;
+
+ case "--all":
+ dumpEvents = true;
+ dumpSerializedSize = true;
+ break;
+ }
+ }
+
+ synchronized (mEvents) {
+ pw.println("Number of events: " + mEvents.size());
+ pw.println("Time span: " +
+ DateUtils.formatElapsedTime(
+ (System.currentTimeMillis() - mEvents.peekFirst().timestamp)
+ / 1000));
+
+ if (dumpSerializedSize) {
+ long dataSize = 0;
+ Parcel p = Parcel.obtain();
+ for (ConnectivityMetricsEvent e : mEvents) {
+ dataSize += 16; // timestamp and 2 stamps
+
+ p.writeParcelable(e.data, 0);
+ }
+ dataSize += p.dataSize();
+ p.recycle();
+ pw.println("Serialized data size: " + dataSize);
+ }
+
+ if (dumpEvents) {
+ pw.println();
+ pw.println("Events:");
+ for (ConnectivityMetricsEvent e : mEvents) {
+ pw.println(e.toString());
}
}
}
+
+ if (!mPendingIntents.isEmpty()) {
+ pw.println();
+ pw.println("Pending intents:");
+ for (PendingIntent pi : mPendingIntents) {
+ pw.println(pi.toString());
+ }
+ }
}
- public void logEvent(ConnectivityMetricsEvent event) {
+ public long logEvent(ConnectivityMetricsEvent event) {
ConnectivityMetricsEvent[] events = new ConnectivityMetricsEvent[]{event};
- logEvents(events);
+ return logEvents(events);
}
- public void logEvents(ConnectivityMetricsEvent[] events) {
+ /**
+ * @param events
+ *
+ * Note: All events must belong to the same component.
+ *
+ * @return 0 on success
+ * <0 if error happened
+ * >0 timestamp after which new events will be accepted
+ */
+ public long logEvents(ConnectivityMetricsEvent[] events) {
enforceConnectivityInternalPermission();
- ConnectivityMetricsEvent[] eventsToSend;
- if (VDBG) {
- for (ConnectivityMetricsEvent e : events) {
- Log.v(TAG, "writeEvent(" + e.toString() + ")");
+ if (events == null || events.length == 0) {
+ Log.wtf(TAG, "No events passed to logEvents()");
+ return -1;
+ }
+
+ int componentTag = events[0].componentTag;
+ if (componentTag < 0 ||
+ componentTag >= ConnectivityMetricsLogger.NUMBER_OF_COMPONENTS) {
+ Log.wtf(TAG, "Unexpected tag: " + componentTag);
+ return -1;
+ }
+
+ synchronized (mThrottlingCounters) {
+ long currentTimeMillis = System.currentTimeMillis();
+ if (currentTimeMillis > mThrottlingIntervalBoundaryMillis) {
+ resetThrottlingCounters(currentTimeMillis);
+ }
+
+ mThrottlingCounters[componentTag] += events.length;
+
+ if (mThrottlingCounters[componentTag] >
+ THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT) {
+ Log.w(TAG, "Too many events from #" + componentTag +
+ ". Block until " + mThrottlingIntervalBoundaryMillis);
+
+ return mThrottlingIntervalBoundaryMillis;
}
}
+ boolean sendPendingIntents = false;
+
synchronized (mEvents) {
for (ConnectivityMetricsEvent e : events) {
- mEvents.add(e);
+ if (e.componentTag != componentTag) {
+ Log.wtf(TAG, "Unexpected tag: " + e.componentTag);
+ return -1;
+ }
+
+ addEvent(e);
}
- eventsToSend = prepareEventsToSendIfReady();
+ mLastEventReference += events.length;
+
+ mEventCounter += events.length;
+ if (mEventCounter >= EVENTS_NOTIFICATION_THRESHOLD) {
+ mEventCounter = 0;
+ sendPendingIntents = true;
+ }
+ }
+
+ if (sendPendingIntents) {
+ synchronized (mPendingIntents) {
+ for (PendingIntent pi : mPendingIntents) {
+ if (VDBG) Log.v(TAG, "Send pending intent");
+ try {
+ pi.send(getContext(), 0, null, null, null);
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Pending intent canceled: " + pi);
+ mPendingIntents.remove(pi);
+ }
+ }
+ }
}
- maybeSendEventsToSubscribers(eventsToSend);
+ return 0;
}
- public boolean subscribe(IConnectivityMetricsLoggerSubscriber subscriber) {
- enforceConnectivityInternalPermission();
- if (VDBG) Log.v(TAG, "subscribe");
+ /**
+ * Retrieve events
+ *
+ * @param reference of the last event previously returned. The function will return
+ * events following it.
+ * If 0 then all events will be returned.
+ * After the function call it will contain reference of the
+ * last returned event.
+ * @return events
+ */
+ public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) {
+ enforceDumpPermission();
+ long ref = reference.value;
+ if (VDBG) Log.v(TAG, "getEvents(" + ref + ")");
- synchronized (mSubscribers) {
- if (mSubscribers.containsKey(subscriber)) {
- Log.e(TAG, "subscriber is already subscribed");
- return false;
+ ConnectivityMetricsEvent[] result;
+ synchronized (mEvents) {
+ if (ref > mLastEventReference) {
+ Log.e(TAG, "Invalid reference");
+ reference.value = mLastEventReference;
+ return null;
}
- final IConnectivityMetricsLoggerSubscriber s = subscriber;
- IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- if (VDBG) Log.v(TAG, "subscriber died");
- synchronized (mSubscribers) {
- mSubscribers.remove(s);
- }
+ if (ref < mLastEventReference - mEvents.size()) {
+ ref = mLastEventReference - mEvents.size();
+ }
+
+ int numEventsToSkip =
+ mEvents.size() // Total number of events
+ - (int)(mLastEventReference - ref); // Number of events to return
+
+ result = new ConnectivityMetricsEvent[mEvents.size() - numEventsToSkip];
+ int i = 0;
+ for (ConnectivityMetricsEvent e : mEvents) {
+ if (numEventsToSkip > 0) {
+ numEventsToSkip--;
+ } else {
+ result[i++] = e;
}
- };
-
- try {
- subscriber.asBinder().linkToDeath(dr, 0);
- mSubscribers.put(subscriber, dr);
- } catch (RemoteException e) {
- Log.e(TAG, "subscribe failed: " + e);
- return false;
}
}
+ reference.value = mLastEventReference;
+
+ return result;
+ }
+
+ public boolean register(PendingIntent newEventsIntent) {
+ enforceDumpPermission();
+ if (VDBG) Log.v(TAG, "register(" + newEventsIntent + ")");
+
+ synchronized (mPendingIntents) {
+ if (mPendingIntents.remove(newEventsIntent)) {
+ Log.w(TAG, "Replacing registered pending intent");
+ }
+ mPendingIntents.add(newEventsIntent);
+ }
+
return true;
}
- public void unsubscribe(IConnectivityMetricsLoggerSubscriber subscriber) {
- enforceConnectivityInternalPermission();
- if (VDBG) Log.v(TAG, "unsubscribe");
- synchronized (mSubscribers) {
- IBinder.DeathRecipient dr = mSubscribers.remove(subscriber);
- if (dr == null) {
- Log.e(TAG, "subscriber is not subscribed");
- return;
+ public void unregister(PendingIntent newEventsIntent) {
+ enforceDumpPermission();
+ if (VDBG) Log.v(TAG, "unregister(" + newEventsIntent + ")");
+
+ synchronized (mPendingIntents) {
+ if (!mPendingIntents.remove(newEventsIntent)) {
+ Log.e(TAG, "Pending intent is not registered");
}
- subscriber.asBinder().unlinkToDeath(dr, 0);
}
}
};
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index d10df02a3f2f..2cba93fdab90 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1211,6 +1211,11 @@ public class Tethering extends BaseNetworkObserver {
Log.e(TAG, "Error Tethering: " + e.toString());
setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
+ try {
+ mNMService.untetherInterface(mIfaceName);
+ } catch (Exception ee) {
+ Log.e(TAG, "Error untethering after failure!" + ee.toString());
+ }
transitionTo(mInitialState);
return;
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 3b0b79a771ef..a111bf925181 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -264,7 +264,12 @@ public class Vpn {
return true;
}
- // Check if the caller is authorized.
+ // Stop an existing always-on VPN from being dethroned by other apps.
+ if (getAlwaysOnPackage() != null) {
+ return false;
+ }
+
+ // Check that the caller is authorized.
enforceControlPermission();
prepareInternal(newPackage);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 7f7ea9d8060c..6e7ea9925f91 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -42,10 +42,10 @@ import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.FactoryTest;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -59,6 +59,7 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
+import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -72,7 +73,31 @@ import java.util.List;
* {@hide}
*/
public final class ContentService extends IContentService.Stub {
- private static final String TAG = "ContentService";
+ static final String TAG = "ContentService";
+ static final boolean DEBUG = false;
+
+ public static class Lifecycle extends SystemService {
+ private ContentService mContentService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ final boolean factoryTest = (FactoryTest
+ .getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL);
+ mContentService = new ContentService(getContext(), factoryTest);
+ publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mContentService);
+ }
+
+ @Override
+ public void onCleanupUser(int userHandle) {
+ synchronized (mContentService.mCache) {
+ mContentService.mCache.remove(userHandle);
+ }
+ }
+ }
private Context mContext;
private boolean mFactoryTest;
@@ -94,12 +119,18 @@ public final class ContentService extends IContentService.Stub {
private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- final Uri data = intent.getData();
- if (data != null) {
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
- UserHandle.USER_NULL);
- final String packageName = data.getSchemeSpecificPart();
- invalidateCacheLocked(userId, packageName, null);
+ synchronized (mCache) {
+ if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+ mCache.clear();
+ } else {
+ final Uri data = intent.getData();
+ if (data != null) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL);
+ final String packageName = data.getSchemeSpecificPart();
+ invalidateCacheLocked(userId, packageName, null);
+ }
+ }
}
}
};
@@ -227,6 +258,11 @@ public final class ContentService extends IContentService.Stub {
packageFilter.addDataScheme("package");
mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
packageFilter, null, null);
+
+ final IntentFilter localeFilter = new IntentFilter();
+ localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
+ mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
+ localeFilter, null, null);
}
public void systemReady() {
@@ -304,12 +340,10 @@ public final class ContentService extends IContentService.Stub {
*/
@Override
public void notifyChange(Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, boolean syncToNetwork,
+ boolean observerWantsSelfNotifications, int flags,
int userHandle) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
- + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
- }
+ if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
+ + " from observer " + observer + ", flags " + Integer.toHexString(flags));
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
@@ -338,16 +372,15 @@ public final class ContentService extends IContentService.Stub {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
synchronized (mRootNode) {
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
- userHandle, calls);
+ flags, userHandle, calls);
}
final int numCalls = calls.size();
for (int i=0; i<numCalls; i++) {
ObserverCall oc = calls.get(i);
try {
oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
- }
+ if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
+ + uri);
} catch (RemoteException ex) {
synchronized (mRootNode) {
Log.w(TAG, "Found dead observer, removing");
@@ -366,7 +399,7 @@ public final class ContentService extends IContentService.Stub {
}
}
}
- if (syncToNetwork) {
+ if ((flags&ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid,
@@ -385,7 +418,8 @@ public final class ContentService extends IContentService.Stub {
public void notifyChange(Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, boolean syncToNetwork) {
- notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
+ notifyChange(uri, observer, observerWantsSelfNotifications,
+ syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
UserHandle.getCallingUserId());
}
@@ -1029,14 +1063,14 @@ public final class ContentService extends IContentService.Stub {
for (int i = 0; i < packageCache.size();) {
final Pair<String, Uri> key = packageCache.keyAt(i);
if (key.second != null && key.second.toString().startsWith(uri.toString())) {
- Slog.d(TAG, "Invalidating cache for key " + key);
+ if (DEBUG) Slog.d(TAG, "Invalidating cache for key " + key);
packageCache.removeAt(i);
} else {
i++;
}
}
} else {
- Slog.d(TAG, "Invalidating cache for package " + providerPackageName);
+ if (DEBUG) Slog.d(TAG, "Invalidating cache for package " + providerPackageName);
packageCache.clear();
}
}
@@ -1080,12 +1114,6 @@ public final class ContentService extends IContentService.Stub {
}
}
- public static ContentService main(Context context, boolean factoryTest) {
- ContentService service = new ContentService(context, factoryTest);
- ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
- return service;
- }
-
/**
* Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL
* permission, if the userHandle is not for the caller.
@@ -1281,8 +1309,8 @@ public final class ContentService extends IContentService.Stub {
}
private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
- boolean observerWantsSelfNotifications, int targetUserHandle,
- ArrayList<ObserverCall> calls) {
+ boolean observerWantsSelfNotifications, int flags,
+ int targetUserHandle, ArrayList<ObserverCall> calls) {
int N = mObservers.size();
IBinder observerBinder = observer == null ? null : observer.asBinder();
for (int i = 0; i < N; i++) {
@@ -1300,9 +1328,29 @@ public final class ContentService extends IContentService.Stub {
|| entry.userHandle == UserHandle.USER_ALL
|| targetUserHandle == entry.userHandle) {
// Make sure the observer is interested in the notification
- if (leaf || (!leaf && entry.notifyForDescendants)) {
- calls.add(new ObserverCall(this, entry.observer, selfChange));
+ if (leaf) {
+ // If we are at the leaf: we always report, unless the sender has asked
+ // to skip observers that are notifying for descendants (since they will
+ // be sending another more specific URI for them).
+ if ((flags&ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS) != 0
+ && entry.notifyForDescendants) {
+ if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer
+ + ": skip notify for descendants");
+ continue;
+ }
+ } else {
+ // If we are not at the leaf: we report if the observer says it wants
+ // to be notified for all descendants.
+ if (!entry.notifyForDescendants) {
+ if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer
+ + ": not monitor descendants");
+ continue;
+ }
}
+ if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf
+ + " flags=" + Integer.toHexString(flags)
+ + " desc=" + entry.notifyForDescendants);
+ calls.add(new ObserverCall(this, entry.observer, selfChange));
}
}
}
@@ -1311,19 +1359,22 @@ public final class ContentService extends IContentService.Stub {
* targetUserHandle is either a hard user handle or is USER_ALL
*/
public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
- boolean observerWantsSelfNotifications, int targetUserHandle,
- ArrayList<ObserverCall> calls) {
+ boolean observerWantsSelfNotifications, int flags,
+ int targetUserHandle, ArrayList<ObserverCall> calls) {
String segment = null;
int segmentCount = countUriSegments(uri);
if (index >= segmentCount) {
// This is the leaf node, notify all observers
+ if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName);
collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
- targetUserHandle, calls);
+ flags, targetUserHandle, calls);
} else if (index < segmentCount){
segment = getUriSegment(uri, index);
+ if (DEBUG) Slog.d(TAG, "Collecting non-leaf observers @ #" + index + " / "
+ + segment);
// Notify any observers at this level who are interested in descendants
collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
- targetUserHandle, calls);
+ flags, targetUserHandle, calls);
}
int N = mChildren.size();
@@ -1331,8 +1382,8 @@ public final class ContentService extends IContentService.Stub {
ObserverNode node = mChildren.get(i);
if (segment == null || node.mName.equals(segment)) {
// We found the child,
- node.collectObserversLocked(uri, index + 1,
- observer, observerWantsSelfNotifications, targetUserHandle, calls);
+ node.collectObserversLocked(uri, index + 1, observer,
+ observerWantsSelfNotifications, flags, targetUserHandle, calls);
if (segment != null) {
break;
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e5342ceec1dc..db41a54f1a0a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1402,12 +1402,24 @@ public class SyncManager {
}
}
+ private void restoreLostPeriodicSyncsIfNeeded(int userId) {
+ List<SyncOperation> periodicSyncs = new ArrayList<SyncOperation>();
+ for (SyncOperation sync : getAllPendingSyncs()) {
+ if (sync.isPeriodic && sync.target.userId == userId) {
+ periodicSyncs.add(sync);
+ }
+ }
+ mSyncStorageEngine.restorePeriodicSyncsIfNeededForUser(userId, periodicSyncs);
+ }
+
private void onUserUnlocked(int userId) {
// Make sure that accounts we're about to use are valid.
AccountManagerService.getSingleton().validateAccounts(userId);
mSyncAdapters.invalidateCache(userId);
+ restoreLostPeriodicSyncsIfNeeded(userId);
+
EndPoint target = new EndPoint(null, null, userId);
updateRunningAccounts(target);
@@ -2578,9 +2590,11 @@ public class SyncManager {
}
}
+ // Cancel all jobs from non-existent accounts.
+ AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts();
List<SyncOperation> ops = getAllPendingSyncs();
for (SyncOperation op: ops) {
- if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) {
+ if (!containsAccountAndUser(allAccounts, op.target.account, op.target.userId)) {
getJobScheduler().cancel(op.jobId);
}
}
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index bc3fc6a47aef..fb23265c2189 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -826,6 +826,35 @@ public class SyncStorageEngine extends Handler {
return true;
}
+ /**
+ * STOPSHIP This is a temporary workaround and should be removed before shipping: b/28052438
+ */
+ void restorePeriodicSyncsIfNeededForUser(int userHandle, List<SyncOperation> periodicSyncs) {
+ if (mPeriodicSyncAddedListener == null) {
+ return;
+ }
+ synchronized (mAuthorities) {
+ for (int i = 0; i < mAuthorities.size(); i++) {
+ AuthorityInfo authority = mAuthorities.valueAt(i);
+ if (authority.target.userId == userHandle && authority.enabled) {
+ boolean periodicSyncAlreadyExists = false;
+ for (SyncOperation sync : periodicSyncs) {
+ if (authority.target.matchesSpec(sync.target)) {
+ periodicSyncAlreadyExists = true;
+ break;
+ }
+ }
+ // The periodic sync must have been lost due to previous bug.
+ if (!periodicSyncAlreadyExists) {
+ mPeriodicSyncAddedListener.onPeriodicSyncAdded(authority.target,
+ new Bundle(), DEFAULT_POLL_FREQUENCY_SECONDS,
+ calculateDefaultFlexTime(DEFAULT_POLL_FREQUENCY_SECONDS));
+ }
+ }
+ }
+ }
+ }
+
public void setMasterSyncAutomatically(boolean flag, int userId) {
synchronized (mAuthorities) {
Boolean auto = mMasterSyncAutomatically.get(userId);
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7b134cab2b95..3d8bf5126638 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -107,6 +107,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
private static final int FINGERPRINT_ACQUIRED_GOOD = 0;
private final String mKeyguardPackage;
private int mCurrentUserId = UserHandle.USER_CURRENT;
+ private int mUserIdForRemove = UserHandle.USER_NULL;
Handler mHandler = new Handler() {
@Override
@@ -205,10 +206,12 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
protected void handleRemoved(long deviceId, int fingerId, int groupId) {
final ClientMonitor client = mRemoveClient;
if (fingerId != 0) {
- removeTemplateForUser(mRemoveClient, fingerId);
+ removeTemplateForUser(mUserIdForRemove, fingerId);
+ } else {
+ mUserIdForRemove = UserHandle.USER_NULL;
}
if (client != null && client.sendRemoved(fingerId, groupId)) {
- removeClient(mRemoveClient);
+ removeClient(client);
}
}
@@ -325,8 +328,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
return false;
}
- private void removeTemplateForUser(ClientMonitor clientMonitor, int fingerId) {
- mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, clientMonitor.userId);
+ private void removeTemplateForUser(int userId, int fingerId) {
+ mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, userId);
}
private void addTemplateForUser(ClientMonitor clientMonitor, int fingerId) {
@@ -488,6 +491,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
stopPendingOperations(true);
mRemoveClient = new ClientMonitor(token, receiver, userId, restricted, token.toString());
+ mUserIdForRemove = mCurrentUserId;
// The fingerprint template ids will be removed when we get confirmation from the HAL
try {
final int result = daemon.remove(fingerId, userId);
@@ -943,10 +947,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
return;
}
-
- // Group ID is arbitrarily set to parent profile user ID. It just represents
- // the default fingerprints for the user.
- final int effectiveGroupId = getEffectiveUserId(groupId);
final int realUserId = Binder.getCallingUid();
final boolean restricted = isRestricted();
@@ -954,7 +954,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
@Override
public void run() {
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
- startAuthentication(token, opId, realUserId, effectiveGroupId, receiver,
+ startAuthentication(token, opId, realUserId, groupId, receiver,
flags, restricted, opPackageName);
}
});
@@ -989,14 +989,10 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
final IFingerprintServiceReceiver receiver) {
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
final boolean restricted = isRestricted();
-
- // Group ID is arbitrarily set to parent profile user ID. It just represents
- // the default fingerprints for the user.
- final int effectiveGroupId = getEffectiveUserId(groupId);
mHandler.post(new Runnable() {
@Override
public void run() {
- startRemove(token, fingerId, effectiveGroupId, receiver, restricted);
+ startRemove(token, fingerId, groupId, receiver, restricted);
}
});
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index a36e6710887e..69c012e3893d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -165,15 +165,13 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected void onStandby(boolean initiatedByCec, int standbyAction) {
assertRunOnServiceThread();
- if (!mService.isControlEnabled() || initiatedByCec) {
+ if (!mService.isControlEnabled() || initiatedByCec || !mAutoTvOff) {
return;
}
switch (standbyAction) {
case HdmiControlService.STANDBY_SCREEN_OFF:
- if (mAutoTvOff) {
- mService.sendCecCommand(
- HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
- }
+ mService.sendCecCommand(
+ HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
break;
case HdmiControlService.STANDBY_SHUTDOWN:
// ACTION_SHUTDOWN is taken as a signal to power off all the devices.
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index 0b2017104358..537df815e3a2 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -21,6 +21,7 @@ import android.os.Build;
import android.os.SystemClock;
import android.util.Pair;
import android.util.Slog;
+import android.util.Log;
import java.util.HashMap;
@@ -42,6 +43,7 @@ final class HdmiLogger {
// Logging duration for same error message.
private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000; // 20s
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
private static final ThreadLocal<HdmiLogger> sLogger = new ThreadLocal<>();
@@ -83,10 +85,9 @@ final class HdmiLogger {
}
private void debugInternal(String logMessage) {
- if (true || IS_USER_BUILD) {
- return;
+ if (DEBUG) {
+ Slog.d(TAG, logMessage);
}
- Slog.d(TAG, logMessage);
}
private static final String toLogString(String logMessage, Object[] objs) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e73beaab6f0b..c7c765bb431e 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -200,6 +200,7 @@ public class InputManagerService extends IInputManager.Stub
private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
int policyFlags);
+ private static native void nativeToggleCapsLock(long ptr, int deviceId);
private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
@@ -2279,5 +2280,10 @@ public class InputManagerService extends IInputManager.Stub
mHandler.obtainMessage(MSG_INPUT_METHOD_SUBTYPE_CHANGED, userId, 0, someArgs)
.sendToTarget();
}
+
+ @Override
+ public void toggleCapsLock(int deviceId) {
+ nativeToggleCapsLock(mPtr, deviceId);
+ }
}
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index fa8620f20a8f..b2350025152f 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -304,7 +304,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
if (toCancel != null) {
- cancelJobImpl(toCancel);
+ cancelJobImpl(toCancel, jobStatus);
}
startTrackingJob(jobStatus, toCancel);
}
@@ -331,7 +331,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
for (int i=0; i<jobsForUser.size(); i++) {
JobStatus toRemove = jobsForUser.get(i);
- cancelJobImpl(toRemove);
+ cancelJobImpl(toRemove, null);
}
}
@@ -360,7 +360,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
} catch (RemoteException e) {
}
}
- cancelJobImpl(toRemove);
+ cancelJobImpl(toRemove, null);
}
}
@@ -377,13 +377,13 @@ public final class JobSchedulerService extends com.android.server.SystemService
toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
}
if (toCancel != null) {
- cancelJobImpl(toCancel);
+ cancelJobImpl(toCancel, null);
}
}
- private void cancelJobImpl(JobStatus cancelled) {
+ private void cancelJobImpl(JobStatus cancelled, JobStatus incomingJob) {
if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
- stopTrackingJob(cancelled, true /* writeBack */);
+ stopTrackingJob(cancelled, incomingJob, true /* writeBack */);
synchronized (mLock) {
// Remove from pending queue.
mPendingJobs.remove(cancelled);
@@ -549,7 +549,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
for (int i = 0; i < mControllers.size(); i++) {
StateController controller = mControllers.get(i);
if (update) {
- controller.maybeStopTrackingJobLocked(jobStatus, true);
+ controller.maybeStopTrackingJobLocked(jobStatus, null, true);
}
controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
}
@@ -561,14 +561,15 @@ public final class JobSchedulerService extends com.android.server.SystemService
* Called when we want to remove a JobStatus object that we've finished executing. Returns the
* object removed.
*/
- private boolean stopTrackingJob(JobStatus jobStatus, boolean writeBack) {
+ private boolean stopTrackingJob(JobStatus jobStatus, JobStatus incomingJob,
+ boolean writeBack) {
synchronized (mLock) {
// Remove from store as well as controllers.
final boolean removed = mJobs.remove(jobStatus, writeBack);
if (removed && mReadyToRock) {
for (int i=0; i<mControllers.size(); i++) {
StateController controller = mControllers.get(i);
- controller.maybeStopTrackingJobLocked(jobStatus, false);
+ controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false);
}
}
return removed;
@@ -696,7 +697,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
// Do not write back immediately if this is a periodic job. The job may get lost if system
// shuts down before it is added back.
- if (!stopTrackingJob(jobStatus, !jobStatus.getJob().isPeriodic())) {
+ if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
if (DEBUG) {
Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
}
@@ -780,7 +781,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
break;
case MSG_STOP_JOB:
- cancelJobImpl((JobStatus)message.obj);
+ cancelJobImpl((JobStatus)message.obj, null);
break;
}
maybeRunPendingJobsH();
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index 2114fc3b07c8..d8490d4de516 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -77,7 +77,7 @@ public class AppIdleController extends StateController {
}
@Override
- public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
mTrackedTasks.remove(jobStatus);
}
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index ac9f42520195..077236443dea 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -87,7 +87,7 @@ public class BatteryController extends StateController {
}
@Override
- public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
if (taskStatus.hasChargingConstraint()) {
mTrackedTasks.remove(taskStatus);
}
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 6ef425a57877..5ad8189da054 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -92,7 +92,7 @@ public class ConnectivityController extends StateController implements
}
@Override
- public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
mTrackedJobs.remove(jobStatus);
}
diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
index c5cf30f4739d..b2f1958bac83 100644
--- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
@@ -84,17 +84,8 @@ public class ContentObserverController extends StateController {
boolean havePendingUris = false;
// If there is a previous job associated with the new job, propagate over
// any pending content URI trigger reports.
- if (lastJob != null && lastJob.contentObserverJobInstance != null
- && lastJob.contentObserverJobInstance
- != taskStatus.contentObserverJobInstance
- && lastJob.contentObserverJobInstance.mChangedAuthorities != null) {
+ if (taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
havePendingUris = true;
- taskStatus.contentObserverJobInstance.mChangedAuthorities
- = lastJob.contentObserverJobInstance.mChangedAuthorities;
- taskStatus.contentObserverJobInstance.mChangedUris
- = lastJob.contentObserverJobInstance.mChangedUris;
- lastJob.contentObserverJobInstance.mChangedAuthorities = null;
- lastJob.contentObserverJobInstance.mChangedUris = null;
}
// If we have previously reported changed authorities/uris, then we failed
// to complete the job with them so will re-record them to report again.
@@ -138,15 +129,34 @@ public class ContentObserverController extends StateController {
}
@Override
- public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
+ boolean forUpdate) {
if (taskStatus.hasContentTriggerConstraint()) {
- if (!forUpdate) {
- // We won't do this reset if being called for an update, because
- // we know it will be immediately followed by maybeStartTrackingJobLocked...
- // and we don't want to lose any content changes in-between.
- if (taskStatus.contentObserverJobInstance != null) {
- taskStatus.contentObserverJobInstance.detach();
- taskStatus.contentObserverJobInstance = null;
+ if (taskStatus.contentObserverJobInstance != null) {
+ if (incomingJob != null && taskStatus.contentObserverJobInstance != null
+ && taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
+ // We are stopping this job, but it is going to be replaced by this given
+ // incoming job. We want to propagate our state over to it, so we don't
+ // lose any content changes that had happend since the last one started.
+ // If there is a previous job associated with the new job, propagate over
+ // any pending content URI trigger reports.
+ if (incomingJob.contentObserverJobInstance == null) {
+ incomingJob.contentObserverJobInstance = new JobInstance(incomingJob);
+ }
+ incomingJob.contentObserverJobInstance.mChangedAuthorities
+ = taskStatus.contentObserverJobInstance.mChangedAuthorities;
+ incomingJob.contentObserverJobInstance.mChangedUris
+ = taskStatus.contentObserverJobInstance.mChangedUris;
+ taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
+ taskStatus.contentObserverJobInstance.mChangedUris = null;
+ } else {
+ // We won't do this reset if being called for an update, because
+ // we know it will be immediately followed by maybeStartTrackingJobLocked...
+ // and we don't want to lose any content changes in-between.
+ if (taskStatus.contentObserverJobInstance != null) {
+ taskStatus.contentObserverJobInstance.detach();
+ taskStatus.contentObserverJobInstance = null;
+ }
}
}
mTrackedTasks.remove(taskStatus);
diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index d2ef6a2e5aa2..64887e8d394d 100644
--- a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -166,7 +166,7 @@ public class DeviceIdleJobsController extends StateController {
}
@Override
- public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
mTrackedTasks.remove(jobStatus);
}
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index d9eb45c6026d..50aa88257ace 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -75,7 +75,7 @@ public class IdleController extends StateController {
}
@Override
- public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
mTrackedTasks.remove(taskStatus);
}
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index ac7f4c3f4756..013903939f18 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -56,7 +56,8 @@ public abstract class StateController {
/**
* Remove task - this will happen if the task is cancelled, completed, etc.
*/
- public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate);
+ public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+ boolean forUpdate);
/**
* Called when a new job is being created to reschedule an old failed job.
*/
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index 35432495942d..ab6768e99878 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -74,7 +74,7 @@ public class TimeController extends StateController {
@Override
public void maybeStartTrackingJobLocked(JobStatus job, JobStatus lastJob) {
if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
- maybeStopTrackingJobLocked(job, false);
+ maybeStopTrackingJobLocked(job, null, false);
boolean isInsert = false;
ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
while (it.hasPrevious()) {
@@ -101,7 +101,7 @@ public class TimeController extends StateController {
* Really an == comparison should be enough, but why play with fate? We'll do <=.
*/
@Override
- public void maybeStopTrackingJobLocked(JobStatus job, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus job, JobStatus incomingJob, boolean forUpdate) {
if (mTrackedJobs.remove(job)) {
checkExpiredDelaysAndResetAlarm();
checkExpiredDeadlinesAndResetAlarm();
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 257c7dadfc5d..5953ddecd222 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -18,12 +18,17 @@ package com.android.server.lights;
import com.android.server.SystemService;
import com.android.server.vr.VrManagerInternal;
+import com.android.server.vr.VrManagerService;
import com.android.server.vr.VrStateListener;
import android.content.Context;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Message;
+import android.os.RemoteException;
import android.os.Trace;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
import android.util.Slog;
public class LightsService extends SystemService {
@@ -164,13 +169,19 @@ public class LightsService extends SystemService {
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
- getLocalService(VrManagerInternal.class).registerListener(mVrStateListener);
+ IVrManager vrManager =
+ (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
+ try {
+ vrManager.registerListener(mVrStateCallbacks);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+ }
}
}
- private final VrStateListener mVrStateListener = new VrStateListener() {
+ private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
@Override
- public void onVrStateChanged(boolean enabled) {
+ public void onVrStateChanged(boolean enabled) throws RemoteException {
LightImpl l = mLights[LightsManager.LIGHT_ID_BACKLIGHT];
if (enabled) {
if (DEBUG) Slog.v(TAG, "VR mode enabled, setting brightness to low persistence");
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 124d7f1b9c97..99c41eae22ae 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -771,10 +771,9 @@ public class NotificationManagerService extends SystemService {
cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
REASON_USER_STOPPED, null);
}
- } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED)) {
- boolean inQuietMode = intent.getBooleanExtra(Intent.EXTRA_QUIET_MODE, false);
+ } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- if (inQuietMode && userHandle >= 0) {
+ if (userHandle >= 0) {
cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
REASON_PROFILE_TURNED_OFF, null);
}
@@ -1008,7 +1007,7 @@ public class NotificationManagerService extends SystemService {
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
getContext().registerReceiver(mIntentReceiver, filter);
IntentFilter pkgFilter = new IntentFilter();
@@ -2898,9 +2897,10 @@ public class NotificationManagerService extends SystemService {
}
private void scheduleSendRankingUpdate() {
- mHandler.removeMessages(MESSAGE_SEND_RANKING_UPDATE);
- Message m = Message.obtain(mHandler, MESSAGE_SEND_RANKING_UPDATE);
- mHandler.sendMessage(m);
+ if (!mHandler.hasMessages(MESSAGE_SEND_RANKING_UPDATE)) {
+ Message m = Message.obtain(mHandler, MESSAGE_SEND_RANKING_UPDATE);
+ mHandler.sendMessage(m);
+ }
}
private void handleSendRankingUpdate() {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index e496132a7451..098b39e50d92 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -595,6 +595,16 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(emergencyInfoPckg, PHONE_PERMISSIONS, true, userId);
}
+ // NFC Tag viewer
+ Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW);
+ nfcTagIntent.setType("vnd.android.cursor.item/ndef_msg");
+ PackageParser.Package nfcTagPkg = getDefaultSystemHandlerActivityPackageLPr(
+ nfcTagIntent, userId);
+ if (nfcTagPkg != null
+ && doesPackageSupportRuntimePermissions(nfcTagPkg)) {
+ grantRuntimePermissionsLPw(nfcTagPkg, CONTACTS_PERMISSIONS, false, userId);
+ grantRuntimePermissionsLPw(nfcTagPkg, PHONE_PERMISSIONS, false, userId);
+ }
mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
}
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 7c71fbc82e77..4c18e15e912a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -60,6 +60,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -77,7 +78,6 @@ public class LauncherAppsService extends SystemService {
@Override
public void onStart() {
- Binder.LOG_RUNTIME_EXCEPTION = true;
publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl);
}
@@ -121,6 +121,21 @@ public class LauncherAppsService extends SystemService {
return getCallingUid();
}
+ final int injectCallingUserId() {
+ return UserHandle.getUserId(injectBinderCallingUid());
+ }
+
+ @VisibleForTesting
+ long injectClearCallingIdentity() {
+ return Binder.clearCallingIdentity();
+ }
+
+ // Injection point.
+ @VisibleForTesting
+ void injectRestoreCallingIdentity(long token) {
+ Binder.restoreCallingIdentity(token);
+ }
+
private int getCallingUserId() {
return UserHandle.getUserId(injectBinderCallingUid());
}
@@ -197,14 +212,13 @@ public class LauncherAppsService extends SystemService {
/**
* Checks if the caller is in the same group as the userToCheck.
*/
- @VisibleForTesting // We override it in unit tests
- void ensureInUserProfiles(UserHandle userToCheck, String message) {
- final int callingUserId = UserHandle.getCallingUserId();
+ private void ensureInUserProfiles(UserHandle userToCheck, String message) {
+ final int callingUserId = injectCallingUserId();
final int targetUserId = userToCheck.getIdentifier();
if (targetUserId == callingUserId) return;
- long ident = Binder.clearCallingIdentity();
+ long ident = injectClearCallingIdentity();
try {
UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
UserInfo targetUserInfo = mUm.getUserInfo(targetUserId);
@@ -214,7 +228,7 @@ public class LauncherAppsService extends SystemService {
throw new SecurityException(message);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ injectRestoreCallingIdentity(ident);
}
}
@@ -239,12 +253,12 @@ public class LauncherAppsService extends SystemService {
* Checks if the user is enabled.
*/
private boolean isUserEnabled(UserHandle user) {
- long ident = Binder.clearCallingIdentity();
+ long ident = injectClearCallingIdentity();
try {
UserInfo targetUserInfo = mUm.getUserInfo(user.getIdentifier());
return targetUserInfo != null && targetUserInfo.isEnabled();
} finally {
- Binder.restoreCallingIdentity(ident);
+ injectRestoreCallingIdentity(ident);
}
}
@@ -345,6 +359,9 @@ public class LauncherAppsService extends SystemService {
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
String packageName, ComponentName componentName, int flags, UserHandle user) {
ensureShortcutPermission(callingPackage, user);
+ if (!isUserEnabled(user)) {
+ return new ParceledListSlice<>(new ArrayList(0));
+ }
return new ParceledListSlice<>(
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
@@ -356,6 +373,9 @@ public class LauncherAppsService extends SystemService {
public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
List<String> ids, UserHandle user) {
ensureShortcutPermission(callingPackage, user);
+ if (!isUserEnabled(user)) {
+ return new ParceledListSlice<>(new ArrayList(0));
+ }
return new ParceledListSlice<>(
mShortcutServiceInternal.getShortcutInfo(getCallingUserId(),
@@ -366,6 +386,10 @@ public class LauncherAppsService extends SystemService {
public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
UserHandle user) {
ensureShortcutPermission(callingPackage, user);
+ if (!isUserEnabled(user)) {
+ throw new IllegalStateException("Cannot pin shortcuts for disabled profile "
+ + user);
+ }
mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
callingPackage, packageName, ids, user.getIdentifier());
@@ -375,6 +399,9 @@ public class LauncherAppsService extends SystemService {
public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
UserHandle user) {
ensureShortcutPermission(callingPackage, user);
+ if (!isUserEnabled(user)) {
+ return 0;
+ }
return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
callingPackage, shortcut, user.getIdentifier());
@@ -384,6 +411,9 @@ public class LauncherAppsService extends SystemService {
public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
UserHandle user) {
ensureShortcutPermission(callingPackage, user);
+ if (!isUserEnabled(user)) {
+ return null;
+ }
return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
callingPackage, shortcut, user.getIdentifier());
@@ -402,6 +432,11 @@ public class LauncherAppsService extends SystemService {
verifyCallingPackage(callingPackage);
ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
+ if (!isUserEnabled(user)) {
+ throw new IllegalStateException("Cannot start a shortcut for disabled profile "
+ + user);
+ }
+
// Even without the permission, pinned shortcuts are always launchable.
if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
callingPackage, packageName, shortcutId, user.getIdentifier())) {
@@ -530,13 +565,13 @@ public class LauncherAppsService extends SystemService {
/** Checks if user is a profile of or same as listeningUser.
* and the user is enabled. */
- boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
+ private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
String debugMsg) {
if (user.getIdentifier() == listeningUser.getIdentifier()) {
if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg);
return true;
}
- long ident = Binder.clearCallingIdentity();
+ long ident = injectClearCallingIdentity();
try {
UserInfo userInfo = mUm.getUserInfo(user.getIdentifier());
UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier());
@@ -557,7 +592,7 @@ public class LauncherAppsService extends SystemService {
return true;
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ injectRestoreCallingIdentity(ident);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0a86a849653c..31eac1f3e0ec 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -76,6 +76,7 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageParser.PARSE_IS_PRIVILEGED;
import static android.content.pm.PackageParser.isApkFile;
+import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
@@ -109,12 +110,14 @@ import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.IDevicePolicyManager;
import android.app.admin.SecurityLog;
import android.app.backup.IBackupManager;
+import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentFilter.AuthorityEntry;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
@@ -147,6 +150,7 @@ import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ActivityIntentInfo;
+import android.content.pm.PackageParser.IntentInfo;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageStats;
@@ -320,6 +324,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_INTENT_MATCHING = false;
private static final boolean DEBUG_PACKAGE_SCANNING = false;
private static final boolean DEBUG_VERIFY = false;
+ private static final boolean DEBUG_FILTERS = false;
// Debug output for dexopting. This is shared between PackageManagerService, OtaDexoptService
// and PackageDexOptimizer. All these classes have their own flag to allow switching a single
@@ -445,6 +450,18 @@ public class PackageManagerService extends IPackageManager.Stub {
sBrowserIntent.setData(Uri.parse("http:"));
}
+ /**
+ * The set of all protected actions [i.e. those actions for which a high priority
+ * intent filter is disallowed].
+ */
+ private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
+ static {
+ PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
+ PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
+ PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
+ PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
+ }
+
// Compilation reasons.
public static final int REASON_FIRST_BOOT = 0;
public static final int REASON_BOOT = 1;
@@ -531,6 +548,20 @@ public class PackageManagerService extends IPackageManager.Stub {
* are package location.
*/
final private ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
+ /**
+ * Tracks high priority intent filters for protected actions. During boot, certain
+ * filter actions are protected and should never be allowed to have a high priority
+ * intent filter for them. However, there is one, and only one exception -- the
+ * setup wizard. It must be able to define a high priority intent filter for these
+ * actions to ensure there are no escapes from the wizard. We need to delay processing
+ * of these during boot as we need to look at all of the system packages in order
+ * to know which component is the setup wizard.
+ */
+ private final List<PackageParser.ActivityIntentInfo> mProtectedFilters = new ArrayList<>();
+ /**
+ * Whether or not processing protected filters should be deferred.
+ */
+ private boolean mDeferProtectedFilters = true;
/**
* Tracks existing system packages prior to receiving an OTA. Keys are package name.
@@ -2429,6 +2460,36 @@ public class PackageManagerService extends IPackageManager.Stub {
}
mExpectingBetter.clear();
+ // Resolve protected action filters. Only the setup wizard is allowed to
+ // have a high priority filter for these actions.
+ mSetupWizardPackage = getSetupWizardPackageName();
+ if (mProtectedFilters.size() > 0) {
+ if (DEBUG_FILTERS && mSetupWizardPackage == null) {
+ Slog.i(TAG, "No setup wizard;"
+ + " All protected intents capped to priority 0");
+ }
+ for (ActivityIntentInfo filter : mProtectedFilters) {
+ if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Found setup wizard;"
+ + " allow priority " + filter.getPriority() + ";"
+ + " package: " + filter.activity.info.packageName
+ + " activity: " + filter.activity.className
+ + " priority: " + filter.getPriority());
+ }
+ // skip setup wizard; allow it to keep the high priority filter
+ continue;
+ }
+ Slog.w(TAG, "Protected action; cap priority to 0;"
+ + " package: " + filter.activity.info.packageName
+ + " activity: " + filter.activity.className
+ + " origPrio: " + filter.getPriority());
+ filter.setPriority(0);
+ }
+ }
+ mDeferProtectedFilters = false;
+ mProtectedFilters.clear();
+
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
updateAllSharedLibrariesLPw();
@@ -2531,7 +2592,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
mInstallerService = new PackageInstallerService(context, this);
- mSetupWizardPackage = getSetupWizardPackageName();
final ComponentName ephemeralResolverComponent = getEphemeralResolverLPr();
final ComponentName ephemeralInstallerComponent = getEphemeralInstallerLPr();
@@ -6946,25 +7006,46 @@ public class PackageManagerService extends IPackageManager.Stub {
pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
}
+ UsageStatsManager usageMgr =
+ (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE);
+
int curr = 0;
int total = pkgs.size();
for (PackageParser.Package pkg : pkgs) {
curr++;
+ if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName);
+ }
+ continue;
+ }
+
+ if (!causeFirstBoot && usageMgr.isAppInactive(pkg.packageName)) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Skipping update of of idle app " + pkg.packageName);
+ }
+ continue;
+ }
+
if (DEBUG_DEXOPT) {
Log.i(TAG, "Extracting app " + curr + " of " + total + ": " + pkg.packageName);
}
- if (PackageDexOptimizer.canOptimizePackage(pkg)) {
- // If the cache was pruned, any compiled odex files will likely be out of date
- // and would have to be patched (would be SELF_PATCHOAT, which is deprecated).
- // Instead, force the extraction in this case.
- performDexOpt(pkg.packageName,
- null /* instructionSet */,
- false /* checkProfiles */,
- causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
- false /* force */);
+ if (!isFirstBoot()) {
+ try {
+ ActivityManagerNative.getDefault().showBootMessage(
+ mContext.getResources().getString(R.string.android_upgrading_apk,
+ curr, total), true);
+ } catch (RemoteException e) {
+ }
}
+
+ performDexOpt(pkg.packageName,
+ null /* instructionSet */,
+ false /* checkProfiles */,
+ causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
+ false /* force */);
}
}
@@ -9762,8 +9843,314 @@ public class PackageManagerService extends IPackageManager.Stub {
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}
+ /**
+ * Finds a privileged activity that matches the specified activity names.
+ */
+ private PackageParser.Activity findMatchingActivity(
+ List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
+ for (PackageParser.Activity sysActivity : activityList) {
+ if (sysActivity.info.name.equals(activityInfo.name)) {
+ return sysActivity;
+ }
+ if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
+ return sysActivity;
+ }
+ if (sysActivity.info.targetActivity != null) {
+ if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
+ return sysActivity;
+ }
+ if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
+ return sysActivity;
+ }
+ }
+ }
+ return null;
+ }
+
+ public class IterGenerator<E> {
+ public Iterator<E> generate(ActivityIntentInfo info) {
+ return null;
+ }
+ }
+
+ public class ActionIterGenerator extends IterGenerator<String> {
+ @Override
+ public Iterator<String> generate(ActivityIntentInfo info) {
+ return info.actionsIterator();
+ }
+ }
+
+ public class CategoriesIterGenerator extends IterGenerator<String> {
+ @Override
+ public Iterator<String> generate(ActivityIntentInfo info) {
+ return info.categoriesIterator();
+ }
+ }
+
+ public class SchemesIterGenerator extends IterGenerator<String> {
+ @Override
+ public Iterator<String> generate(ActivityIntentInfo info) {
+ return info.schemesIterator();
+ }
+ }
+
+ public class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
+ @Override
+ public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
+ return info.authoritiesIterator();
+ }
+ }
+
+ /**
+ * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
+ * MODIFIED. Do not pass in a list that should not be changed.
+ */
+ private <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
+ IterGenerator<T> generator, Iterator<T> searchIterator) {
+ // loop through the set of actions; every one must be found in the intent filter
+ while (searchIterator.hasNext()) {
+ // we must have at least one filter in the list to consider a match
+ if (intentList.size() == 0) {
+ break;
+ }
+
+ final T searchAction = searchIterator.next();
+
+ // loop through the set of intent filters
+ final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
+ while (intentIter.hasNext()) {
+ final ActivityIntentInfo intentInfo = intentIter.next();
+ boolean selectionFound = false;
+
+ // loop through the intent filter's selection criteria; at least one
+ // of them must match the searched criteria
+ final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
+ while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
+ final T intentSelection = intentSelectionIter.next();
+ if (intentSelection != null && intentSelection.equals(searchAction)) {
+ selectionFound = true;
+ break;
+ }
+ }
+
+ // the selection criteria wasn't found in this filter's set; this filter
+ // is not a potential match
+ if (!selectionFound) {
+ intentIter.remove();
+ }
+ }
+ }
+ }
+
+ private boolean isProtectedAction(ActivityIntentInfo filter) {
+ final Iterator<String> actionsIter = filter.actionsIterator();
+ while (actionsIter != null && actionsIter.hasNext()) {
+ final String filterAction = actionsIter.next();
+ if (PROTECTED_ACTIONS.contains(filterAction)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adjusts the priority of the given intent filter according to policy.
+ * <p>
+ * <ul>
+ * <li>The priority for non privileged applications is capped to '0'</li>
+ * <li>The priority for protected actions on privileged applications is capped to '0'</li>
+ * <li>The priority for unbundled updates to privileged applications is capped to the
+ * priority defined on the system partition</li>
+ * </ul>
+ * <p>
+ * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
+ * allowed to obtain any priority on any action.
+ */
+ private void adjustPriority(
+ List<PackageParser.Activity> systemActivities, ActivityIntentInfo intent) {
+ // nothing to do; priority is fine as-is
+ if (intent.getPriority() <= 0) {
+ return;
+ }
+
+ final ActivityInfo activityInfo = intent.activity.info;
+ final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
+
+ final boolean privilegedApp =
+ ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
+ if (!privilegedApp) {
+ // non-privileged applications can never define a priority >0
+ Slog.w(TAG, "Non-privileged app; cap priority to 0;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ intent.setPriority(0);
+ return;
+ }
+
+ if (systemActivities == null) {
+ // the system package is not disabled; we're parsing the system partition
+ if (isProtectedAction(intent)) {
+ if (mDeferProtectedFilters) {
+ // We can't deal with these just yet. No component should ever obtain a
+ // >0 priority for a protected actions, with ONE exception -- the setup
+ // wizard. The setup wizard, however, cannot be known until we're able to
+ // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
+ // until all intent filters have been processed. Chicken, meet egg.
+ // Let the filter temporarily have a high priority and rectify the
+ // priorities after all system packages have been scanned.
+ mProtectedFilters.add(intent);
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Protected action; save for later;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
+ return;
+ } else {
+ if (DEBUG_FILTERS && mSetupWizardPackage == null) {
+ Slog.i(TAG, "No setup wizard;"
+ + " All protected intents capped to priority 0");
+ }
+ if (intent.activity.info.packageName.equals(mSetupWizardPackage)) {
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Found setup wizard;"
+ + " allow priority " + intent.getPriority() + ";"
+ + " package: " + intent.activity.info.packageName
+ + " activity: " + intent.activity.className
+ + " priority: " + intent.getPriority());
+ }
+ // setup wizard gets whatever it wants
+ return;
+ }
+ Slog.w(TAG, "Protected action; cap priority to 0;"
+ + " package: " + intent.activity.info.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ intent.setPriority(0);
+ return;
+ }
+ }
+ // privileged apps on the system image get whatever priority they request
+ return;
+ }
+
+ // privileged app unbundled update ... try to find the same activity
+ final PackageParser.Activity foundActivity =
+ findMatchingActivity(systemActivities, activityInfo);
+ if (foundActivity == null) {
+ // this is a new activity; it cannot obtain >0 priority
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "New activity; cap priority to 0;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
+ intent.setPriority(0);
+ return;
+ }
+
+ // found activity, now check for filter equivalence
+
+ // a shallow copy is enough; we modify the list, not its contents
+ final List<ActivityIntentInfo> intentListCopy =
+ new ArrayList<>(foundActivity.intents);
+ final List<ActivityIntentInfo> foundFilters = findFilters(intent);
+
+ // find matching action subsets
+ final Iterator<String> actionsIterator = intent.actionsIterator();
+ if (actionsIterator != null) {
+ getIntentListSubset(
+ intentListCopy, new ActionIterGenerator(), actionsIterator);
+ if (intentListCopy.size() == 0) {
+ // no more intents to match; we're not equivalent
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Mismatched action; cap priority to 0;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
+ intent.setPriority(0);
+ return;
+ }
+ }
+
+ // find matching category subsets
+ final Iterator<String> categoriesIterator = intent.categoriesIterator();
+ if (categoriesIterator != null) {
+ getIntentListSubset(intentListCopy, new CategoriesIterGenerator(),
+ categoriesIterator);
+ if (intentListCopy.size() == 0) {
+ // no more intents to match; we're not equivalent
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Mismatched category; cap priority to 0;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
+ intent.setPriority(0);
+ return;
+ }
+ }
+
+ // find matching schemes subsets
+ final Iterator<String> schemesIterator = intent.schemesIterator();
+ if (schemesIterator != null) {
+ getIntentListSubset(intentListCopy, new SchemesIterGenerator(),
+ schemesIterator);
+ if (intentListCopy.size() == 0) {
+ // no more intents to match; we're not equivalent
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
+ intent.setPriority(0);
+ return;
+ }
+ }
+
+ // find matching authorities subsets
+ final Iterator<IntentFilter.AuthorityEntry>
+ authoritiesIterator = intent.authoritiesIterator();
+ if (authoritiesIterator != null) {
+ getIntentListSubset(intentListCopy,
+ new AuthoritiesIterGenerator(),
+ authoritiesIterator);
+ if (intentListCopy.size() == 0) {
+ // no more intents to match; we're not equivalent
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Mismatched authority; cap priority to 0;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
+ intent.setPriority(0);
+ return;
+ }
+ }
+
+ // we found matching filter(s); app gets the max priority of all intents
+ int cappedPriority = 0;
+ for (int i = intentListCopy.size() - 1; i >= 0; --i) {
+ cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
+ }
+ if (intent.getPriority() > cappedPriority) {
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Found matching filter(s);"
+ + " cap priority to " + cappedPriority + ";"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
+ intent.setPriority(cappedPriority);
+ return;
+ }
+ // all this for nothing; the requested priority was <= what was on the system
+ }
+
public final void addActivity(PackageParser.Activity a, String type) {
- final boolean systemApp = a.info.applicationInfo.isSystemApp();
mActivities.put(a.getComponentName(), a);
if (DEBUG_SHOW_INFO)
Log.v(
@@ -9774,10 +10161,12 @@ public class PackageManagerService extends IPackageManager.Stub {
final int NI = a.intents.size();
for (int j=0; j<NI; j++) {
PackageParser.ActivityIntentInfo intent = a.intents.get(j);
- if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
- intent.setPriority(0);
- Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
- + a.className + " with priority > 0, forcing to 0");
+ if ("activity".equals(type)) {
+ final PackageSetting ps =
+ mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName);
+ final List<PackageParser.Activity> systemActivities =
+ ps != null && ps.pkg != null ? ps.pkg.activities : null;
+ adjustPriority(systemActivities, intent);
}
if (DEBUG_SHOW_INFO) {
Log.v(TAG, " IntentFilter:");
@@ -9927,18 +10316,6 @@ public class PackageManagerService extends IPackageManager.Stub {
out.println();
}
-// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
-// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
-// final List<ResolveInfo> retList = Lists.newArrayList();
-// while (i.hasNext()) {
-// final ResolveInfo resolveInfo = i.next();
-// if (isEnabledLP(resolveInfo.activityInfo)) {
-// retList.add(resolveInfo);
-// }
-// }
-// return retList;
-// }
-
// Keys are String (activity class name), values are Activity.
private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
= new ArrayMap<ComponentName, PackageParser.Activity>();
@@ -11290,8 +11667,8 @@ public class PackageManagerService extends IPackageManager.Stub {
* @return the current "allow unknown sources" setting
*/
private int getUnknownSourcesSettings() {
- return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
- android.provider.Settings.Global.INSTALL_NON_MARKET_APPS,
+ return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
+ android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
-1);
}
@@ -11779,8 +12156,23 @@ public class PackageManagerService extends IPackageManager.Stub {
// predecessor. As a security measure, this is permited only if this is not a
// version downgrade or if the predecessor package is marked as debuggable and
// a downgrade is explicitly requested.
- if (((dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0)
- || ((installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0)) {
+ //
+ // On debuggable platform builds, downgrades are permitted even for
+ // non-debuggable packages to make testing easier. Debuggable platform builds do
+ // not offer security guarantees and thus it's OK to disable some security
+ // mechanisms to make debugging/testing easier on those builds. However, even on
+ // debuggable builds downgrades of packages are permitted only if requested via
+ // installFlags. This is because we aim to keep the behavior of debuggable
+ // platform builds as close as possible to the behavior of non-debuggable
+ // platform builds.
+ final boolean downgradeRequested =
+ (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+ final boolean packageDebuggable =
+ (dataOwnerPkg.applicationInfo.flags
+ & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+ final boolean downgradePermitted =
+ (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable));
+ if (!downgradePermitted) {
try {
checkDowngrade(dataOwnerPkg, pkgLite);
} catch (PackageManagerException e) {
@@ -12255,8 +12647,6 @@ public class PackageManagerService extends IPackageManager.Stub {
* Called after the source arguments are copied. This is used mostly for
* MoveParams when it needs to read the source file to put it in the
* destination.
- *
- * @return
*/
int doPostCopy(int uid) {
return PackageManager.INSTALL_SUCCEEDED;
@@ -13883,14 +14273,11 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
try {
PackageParser.collectCertificates(pkg, parseFlags);
} catch (PackageParserException e) {
res.setError("Failed collect during installPackageLI", e);
return;
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
// Get rid of all references to package scan path via parser.
@@ -15502,17 +15889,14 @@ public class PackageManagerService extends IPackageManager.Stub {
// Otherwise, reset the permission.
final int revokeResult = permissionsState.revokeRuntimePermission(bp, userId);
switch (revokeResult) {
- case PERMISSION_OPERATION_SUCCESS: {
- writeRuntimePermissions = true;
- } break;
-
+ case PERMISSION_OPERATION_SUCCESS:
case PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
writeRuntimePermissions = true;
final int appId = ps.appId;
mHandler.post(new Runnable() {
@Override
public void run() {
- killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);
+ killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
}
});
} break;
@@ -16632,7 +17016,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
intent.addCategory(Intent.CATEGORY_SETUP_WIZARD);
final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
- MATCH_SYSTEM_ONLY | MATCH_DISABLED_COMPONENTS, UserHandle.myUserId());
+ MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
+ | MATCH_DISABLED_COMPONENTS,
+ UserHandle.myUserId());
if (matches.size() == 1) {
return matches.get(0).getComponentInfo().packageName;
} else {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 7aefcb82a158..5c1e7a8dde9b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2159,6 +2159,9 @@ public class ShortcutService extends IShortcutService.Stub {
case "refresh-default-launcher":
handleRefreshDefaultLauncher();
break;
+ case "unload-user":
+ handleUnloadUser();
+ break;
default:
return handleDefaultCommands(cmd);
}
@@ -2196,6 +2199,10 @@ public class ShortcutService extends IShortcutService.Stub {
pw.println("cmd shortcut refresh-default-launcher [--user USER_ID]");
pw.println(" Refresh the cached default launcher");
pw.println();
+ pw.println("cmd shortcut unload-user [--user USER_ID]");
+ pw.println(" Unload a user from the memory");
+ pw.println(" (This should not affect any observable behavior)");
+ pw.println();
}
private int handleResetThrottling() throws CommandException {
@@ -2267,6 +2274,12 @@ public class ShortcutService extends IShortcutService.Stub {
clearLauncher();
showLauncher();
}
+
+ private void handleUnloadUser() throws CommandException {
+ parseOptions(/* takeUser =*/ true);
+
+ ShortcutService.this.handleCleanupUser(mUserId);
+ }
}
// === Unit test support ===
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 3ff46acb5d31..06a91fb0c857 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -500,6 +500,9 @@ public class UserManagerService extends IUserManager.Stub {
if (mRemovingUserIds.get(profile.id)) {
continue;
}
+ if (profile.partial) {
+ continue;
+ }
users.add(userWithName(profile));
}
return users;
@@ -573,12 +576,26 @@ public class UserManagerService extends IUserManager.Stub {
private void broadcastProfileAvailabilityChanges(UserHandle profileHandle,
UserHandle parentHandle, boolean inQuietMode) {
- Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+ Intent intent = new Intent();
+ if (inQuietMode) {
+ intent.setAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
+ } else {
+ intent.setAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+ }
intent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
intent.putExtra(Intent.EXTRA_USER, profileHandle);
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, parentHandle);
+
+ //TODO: remove once Launcher3 is updated.
+ Intent oldIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+ oldIntent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
+ oldIntent.putExtra(Intent.EXTRA_USER, profileHandle);
+ oldIntent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
+ oldIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mContext.sendBroadcastAsUser(oldIntent, parentHandle);
+
}
@Override
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 4b355de62e87..364e9fa6719c 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -425,6 +425,18 @@ public class UserRestrictionsUtils {
}
}
}
+ break;
+ case UserManager.DISALLOW_SAFE_BOOT:
+ // Unlike with the other restrictions, we want to propagate the new value to
+ // the system settings even if it is false. The other restrictions modify
+ // settings which could be manually changed by the user from the Settings app
+ // after the policies enforcing these restrictions have been revoked, so we
+ // leave re-setting of those settings to the user.
+ android.provider.Settings.Global.putInt(
+ context.getContentResolver(),
+ android.provider.Settings.Global.SAFE_BOOT_DISALLOWED,
+ newValue ? 1 : 0);
+ break;
}
} finally {
Binder.restoreCallingIdentity(id);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 14d0457e41c1..fb56a0c7ee3e 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -69,6 +69,7 @@ import android.graphics.Rect;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
+import android.hardware.input.InputManagerInternal;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -107,6 +108,7 @@ import android.telecom.TelecomManager;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.MutableBoolean;
import android.util.Slog;
import android.util.SparseArray;
import android.util.LongSparseArray;
@@ -304,6 +306,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowManagerInternal mWindowManagerInternal;
PowerManager mPowerManager;
ActivityManagerInternal mActivityManagerInternal;
+ InputManagerInternal mInputManagerInternal;
DreamManagerInternal mDreamManagerInternal;
PowerManagerInternal mPowerManagerInternal;
IStatusBarService mStatusBarService;
@@ -396,6 +399,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile boolean mBeganFromNonInteractive;
volatile int mPowerKeyPressCounter;
volatile boolean mEndCallKeyHandled;
+ volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
+ volatile boolean mGoingToSleep;
boolean mRecentsVisible;
int mRecentAppsHeldModifiers;
@@ -601,6 +606,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mConsumeSearchKeyUp;
boolean mAssistKeyLongPressed;
boolean mPendingMetaAction;
+ boolean mPendingCapsLockToggle;
+ int mMetaState;
+ int mInitialMetaState;
boolean mForceShowSystemBars;
// support for activating the lock screen while the screen is on
@@ -685,6 +693,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
= new LogDecelerateInterpolator(100, 0);
private boolean mForceWindowDrawsStatusBarBackground;
+ private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
private static final int MSG_ENABLE_POINTER_LOCATION = 1;
private static final int MSG_DISABLE_POINTER_LOCATION = 2;
@@ -1032,7 +1041,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
GestureLauncherService.class);
boolean gesturedServiceIntercepted = false;
if (gestureService != null) {
- gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive);
+ gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
+ mTmpBoolean);
+ if (mTmpBoolean.value && mGoingToSleep) {
+ mCameraGestureTriggeredDuringGoingToSleep = true;
+ }
}
// If the power key has still not yet been handled, then detect short
@@ -1486,6 +1499,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs = windowManagerFuncs;
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+ mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1817,41 +1831,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-
- // Height of the navigation bar when presented horizontally at bottom
- mNavigationBarHeightForRotationDefault[mPortraitRotation] =
- mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
- res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
- mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
- mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_height_landscape);
-
- // Width of the navigation bar when presented vertically along one side
- mNavigationBarWidthForRotationDefault[mPortraitRotation] =
- mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
- mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
- mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
- res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
-
- // Height of the navigation bar when presented horizontally at bottom
- mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
- mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
- res.getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_height_car_mode);
- mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
- mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
-
- // Width of the navigation bar when presented vertically along one side
- mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
- mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
- mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
- mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
- res.getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_width_car_mode);
-
// SystemUI (status bar) layout policy
int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
@@ -1860,6 +1839,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mNavigationBarCanMove = width != height && shortSizeDp < 600;
mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
+
// Allow a system property to override this. Used by the emulator.
// See also hasNavigationBar().
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
@@ -2290,6 +2270,46 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ @Override
+ public void onConfigurationChanged() {
+ final Resources res = mContext.getResources();
+
+ mStatusBarHeight =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+
+ // Height of the navigation bar when presented horizontally at bottom
+ mNavigationBarHeightForRotationDefault[mPortraitRotation] =
+ mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
+ mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
+ mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height_landscape);
+
+ // Width of the navigation bar when presented vertically along one side
+ mNavigationBarWidthForRotationDefault[mPortraitRotation] =
+ mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
+ mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
+ mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
+
+ // Height of the navigation bar when presented horizontally at bottom
+ mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
+ mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
+ res.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height_car_mode);
+ mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
+ mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
+
+ // Width of the navigation bar when presented vertically along one side
+ mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
+ mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
+ mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
+ mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
+ res.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_width_car_mode);
+ }
+
/** {@inheritDoc} */
@Override
public int windowTypeToLayerLw(int type) {
@@ -2954,6 +2974,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
mPendingMetaAction = false;
}
+ // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
+ if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
+ mPendingCapsLockToggle = false;
+ }
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
@@ -3202,6 +3226,38 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ // Toggle Caps Lock on META-ALT.
+ boolean actionTriggered = false;
+ if (KeyEvent.isModifierKey(keyCode)) {
+ if (!mPendingCapsLockToggle) {
+ // Start tracking meta state for combo.
+ mInitialMetaState = mMetaState;
+ mPendingCapsLockToggle = true;
+ } else if (event.getAction() == KeyEvent.ACTION_UP) {
+ int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
+ int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
+
+ // Check for Caps Lock toggle
+ if ((metaOnMask != 0) && (altOnMask != 0)) {
+ // Check if nothing else is pressed
+ if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
+ // Handle Caps Lock Toggle
+ mInputManagerInternal.toggleCapsLock(event.getDeviceId());
+ actionTriggered = true;
+ }
+ }
+
+ // Always stop tracking when key goes up.
+ mPendingCapsLockToggle = false;
+ }
+ }
+ // Store current meta state to be able to evaluate it later.
+ mMetaState = metaState;
+
+ if (actionTriggered) {
+ return -1;
+ }
+
if (KeyEvent.isMetaKey(keyCode)) {
if (down) {
mPendingMetaAction = true;
@@ -5948,6 +6004,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void startedGoingToSleep(int why) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
+ mCameraGestureTriggeredDuringGoingToSleep = false;
+ mGoingToSleep = true;
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedGoingToSleep(why);
}
@@ -5960,6 +6018,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
+ mGoingToSleep = false;
+
// We must get this work done here because the power manager will drop
// the wake lock and let the system suspend once this function returns.
synchronized (mLock) {
@@ -5969,8 +6029,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateLockScreenTimeout();
}
if (mKeyguardDelegate != null) {
- mKeyguardDelegate.onFinishedGoingToSleep(why);
+ mKeyguardDelegate.onFinishedGoingToSleep(why,
+ mCameraGestureTriggeredDuringGoingToSleep);
}
+ mCameraGestureTriggeredDuringGoingToSleep = false;
}
// Called on the PowerManager's Notifier thread.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 8d296d505c4c..52e588015177 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -294,9 +294,9 @@ public class KeyguardServiceDelegate {
mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;
}
- public void onFinishedGoingToSleep(int why) {
+ public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
if (mKeyguardService != null) {
- mKeyguardService.onFinishedGoingToSleep(why);
+ mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered);
}
mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 429b18866a61..dacdec042a45 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -117,9 +117,9 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
@Override
- public void onFinishedGoingToSleep(int reason) {
+ public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {
try {
- mService.onFinishedGoingToSleep(reason);
+ mService.onFinishedGoingToSleep(reason, cameraGestureTriggered);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ff5a0f967b54..8cd536de9b54 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -53,6 +53,8 @@ import android.provider.Settings;
import android.provider.Settings.Secure;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -72,6 +74,7 @@ import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import com.android.server.vr.VrManagerInternal;
+import com.android.server.vr.VrManagerService;
import com.android.server.vr.VrStateListener;
import libcore.util.Objects;
@@ -538,7 +541,10 @@ public final class PowerManagerService extends SystemService
@Override
public void onBootPhase(int phase) {
synchronized (mLock) {
- if (phase == PHASE_BOOT_COMPLETED) {
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ incrementBootCount();
+
+ } else if (phase == PHASE_BOOT_COMPLETED) {
final long now = SystemClock.uptimeMillis();
mBootCompleted = true;
mDirty |= DIRTY_BOOT_COMPLETED;
@@ -553,8 +559,6 @@ public final class PowerManagerService extends SystemService
}
}
mBootCompletedRunnables = null;
-
- incrementBootCount();
}
}
}
@@ -657,7 +661,13 @@ public final class PowerManagerService extends SystemService
resolver.registerContentObserver(Settings.Secure.getUriFor(
Secure.BRIGHTNESS_USE_TWILIGHT),
false, mSettingsObserver, UserHandle.USER_ALL);
- getLocalService(VrManagerInternal.class).registerListener(mVrStateListener);
+ IVrManager vrManager =
+ (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
+ try {
+ vrManager.registerListener(mVrStateCallbacks);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+ }
// Go.
readConfigurationLocked();
updateSettingsLocked();
@@ -3006,7 +3016,7 @@ public final class PowerManagerService extends SystemService
}
}
- private final VrStateListener mVrStateListener = new VrStateListener() {
+ private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
@Override
public void onVrStateChanged(boolean enabled) {
powerHintInternal(POWER_HINT_VR_MODE, enabled ? 1 : 0);
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 858f7c70663c..9c2c6bfe828c 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -375,7 +375,7 @@ public class TrustAgentWrapper {
} else {
mTrustAgentService.onConfigure(Collections.EMPTY_LIST, null);
}
- final long maxTimeToLock = dpm.getMaximumTimeToLock(null);
+ final long maxTimeToLock = dpm.getMaximumTimeToLockForUserAndProfiles(mUserId);
if (maxTimeToLock != mMaximumTimeToLock) {
// If the timeout changes, cancel the alarm and send a timeout event to have
// the agent re-evaluate trust.
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 93bb9d795ddd..1bbb9f52c818 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -31,13 +31,6 @@ public abstract class VrManagerInternal {
public static final int NO_ERROR = 0;
/**
- * Return current VR mode state.
- *
- * @return {@code true} if VR mode is enabled.
- */
- public abstract boolean isInVrMode();
-
- /**
* Return {@code true} if the given package is the currently bound VrListenerService for the
* given user.
*
@@ -59,22 +52,6 @@ public abstract class VrManagerInternal {
public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
int userId, @NonNull ComponentName calling);
- /**
- * Add a listener for VR mode state changes.
- * <p>
- * This listener will immediately be called with the current VR mode state.
- * </p>
- * @param listener the listener instance to add.
- */
- public abstract void registerListener(@NonNull VrStateListener listener);
-
- /**
- * Remove the listener from the current set of listeners.
- *
- * @param listener the listener to remove.
- */
- public abstract void unregisterListener(@NonNull VrStateListener listener);
-
/**
* Return NO_ERROR if the given package is installed on the device and enabled as a
* VrListenerService for the given current user, or a negative error code indicating a failure.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index c572e766f1ec..e6e5a2db0725 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -15,6 +15,7 @@
*/
package com.android.server.vr;
+import android.Manifest;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.annotation.NonNull;
@@ -29,11 +30,15 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.vr.IVrListener;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
import android.service.vr.VrListenerService;
import android.util.ArraySet;
import android.util.Slog;
@@ -46,6 +51,7 @@ import com.android.server.utils.ManagedApplicationService;
import com.android.server.utils.ManagedApplicationService.BinderChecker;
import java.lang.StringBuilder;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
@@ -75,6 +81,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
public static final String TAG = "VrManagerService";
+ public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
+
private static native void initializeNative();
private static native void setVrModeNative(boolean enabled);
@@ -84,7 +92,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC
// State protected by mLock
private boolean mVrModeEnabled;
- private final Set<VrStateListener> mListeners = new ArraySet<>();
private EnabledComponentsObserver mComponentObserver;
private ManagedApplicationService mCurrentVrService;
private Context mContext;
@@ -92,10 +99,37 @@ public class VrManagerService extends SystemService implements EnabledComponentC
private int mCurrentVrModeUser;
private boolean mWasDefaultGranted;
private boolean mGuard;
+ private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
+ new RemoteCallbackList<>();
private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
private String mPreviousNotificationPolicyAccessPackage;
private String mPreviousManageOverlayPackage;
+ private static final int MSG_VR_STATE_CHANGE = 0;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_VR_STATE_CHANGE : {
+ boolean state = (msg.arg1 == 1);
+ int i = mRemoteCallbacks.beginBroadcast();
+ while (i > 0) {
+ i--;
+ try {
+ mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
+ } catch (RemoteException e) {
+ // Noop
+ }
+ }
+ mRemoteCallbacks.finishBroadcast();
+ } break;
+ default :
+ throw new IllegalStateException("Unknown message type: " + msg.what);
+ }
+ }
+ };
+
private static final BinderChecker sBinderChecker = new BinderChecker() {
@Override
public IInterface asInterface(IBinder binder) {
@@ -125,34 +159,55 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- /**
- * Implementation of VrManagerInternal. Callable only from system services.
- */
- private final class LocalService extends VrManagerInternal {
+ private final IVrManager mVrManager = new IVrManager.Stub() {
+
@Override
- public boolean isInVrMode() {
- return VrManagerService.this.getVrMode();
+ public void registerListener(IVrStateCallbacks cb) {
+ enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+ if (cb == null) {
+ throw new IllegalArgumentException("Callback binder object is null.");
+ }
+
+ VrManagerService.this.addStateCallback(cb);
}
@Override
- public void setVrMode(boolean enabled, ComponentName packageName, int userId,
- ComponentName callingPackage) {
- VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
+ public void unregisterListener(IVrStateCallbacks cb) {
+ enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+ if (cb == null) {
+ throw new IllegalArgumentException("Callback binder object is null.");
+ }
+
+ VrManagerService.this.removeStateCallback(cb);
}
@Override
- public boolean isCurrentVrListener(String packageName, int userId) {
- return VrManagerService.this.isCurrentVrListener(packageName, userId);
+ public boolean getVrModeState() {
+ return VrManagerService.this.getVrMode();
+ }
+
+ };
+
+ private void enforceCallerPermission(String permission) {
+ if (mContext.checkCallingOrSelfPermission(permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold the permission " + permission);
}
+ }
+ /**
+ * Implementation of VrManagerInternal. Callable only from system services.
+ */
+ private final class LocalService extends VrManagerInternal {
@Override
- public void registerListener(VrStateListener listener) {
- VrManagerService.this.addListener(listener);
+ public void setVrMode(boolean enabled, ComponentName packageName, int userId,
+ ComponentName callingPackage) {
+ VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
}
@Override
- public void unregisterListener(VrStateListener listener) {
- VrManagerService.this.removeListener(listener);
+ public boolean isCurrentVrListener(String packageName, int userId) {
+ return VrManagerService.this.isCurrentVrListener(packageName, userId);
}
@Override
@@ -173,6 +228,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
publishLocalService(VrManagerInternal.class, new LocalService());
+ publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
}
@Override
@@ -551,9 +607,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
* Note: Must be called while holding {@code mLock}.
*/
private void onVrModeChangedLocked() {
- for (VrStateListener l : mListeners) {
- l.onVrStateChanged(mVrModeEnabled);
- }
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
+ (mVrModeEnabled) ? 1 : 0, 0));
}
/**
@@ -577,9 +632,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- private boolean getVrMode() {
+ private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
synchronized (mLock) {
- return mVrModeEnabled;
+ return mComponentObserver.isValid(targetPackageName, userId);
}
}
@@ -593,21 +648,21 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- private void addListener(VrStateListener listener) {
- synchronized (mLock) {
- mListeners.add(listener);
- }
+ /*
+ * Implementation of IVrManager calls.
+ */
+
+ private void addStateCallback(IVrStateCallbacks cb) {
+ mRemoteCallbacks.register(cb);
}
- private void removeListener(VrStateListener listener) {
- synchronized (mLock) {
- mListeners.remove(listener);
- }
+ private void removeStateCallback(IVrStateCallbacks cb) {
+ mRemoteCallbacks.unregister(cb);
}
- private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
+ private boolean getVrMode() {
synchronized (mLock) {
- return mComponentObserver.isValid(targetPackageName, userId);
+ return mVrModeEnabled;
}
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUtilityImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index aaa7977208a1..9486cfdb87a0 100644
--- a/services/core/java/com/android/server/webkit/WebViewUtilityImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -19,15 +19,22 @@ package com.android.server.webkit;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.content.Context;
+import android.content.pm.IPackageDeleteObserver;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
import android.content.res.XmlResourceParser;
+import android.os.Build;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings.Global;
import android.provider.Settings;
import android.util.AndroidRuntimeException;
import android.util.Log;
-import android.webkit.WebViewFactory;
import android.webkit.WebViewFactory.MissingWebViewPackageException;
+import android.webkit.WebViewFactory;
import android.webkit.WebViewProviderInfo;
import com.android.internal.util.XmlUtils;
@@ -42,8 +49,8 @@ import org.xmlpull.v1.XmlPullParserException;
* Default implementation for the WebView preparation Utility interface.
* @hide
*/
-public class WebViewUtilityImpl implements WebViewUtilityInterface {
- private static final String TAG = WebViewUtilityImpl.class.getSimpleName();
+public class SystemImpl implements SystemInterface {
+ private static final String TAG = SystemImpl.class.getSimpleName();
private static final String TAG_START = "webviewproviders";
private static final String TAG_WEBVIEW_PROVIDER = "webviewprovider";
private static final String TAG_PACKAGE_NAME = "packageName";
@@ -103,9 +110,7 @@ public class WebViewUtilityImpl implements WebViewUtilityInterface {
Log.e(TAG, "Found an element that is not a webview provider");
}
}
- } catch(XmlPullParserException e) {
- throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
- } catch(IOException e) {
+ } catch (XmlPullParserException | IOException e) {
throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
} finally {
if (parser != null) parser.close();
@@ -113,6 +118,11 @@ public class WebViewUtilityImpl implements WebViewUtilityInterface {
return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
}
+ public int getFactoryPackageVersion(String packageName) throws NameNotFoundException {
+ PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+ return pm.getPackageInfo(packageName, PackageManager.MATCH_FACTORY_ONLY).versionCode;
+ }
+
/**
* Reads all signatures at the current depth (within the current provider) from the XML parser.
*/
@@ -158,4 +168,70 @@ public class WebViewUtilityImpl implements WebViewUtilityInterface {
} catch (RemoteException e) {
}
}
+
+ @Override
+ public boolean isFallbackLogicEnabled() {
+ // Note that this is enabled by default (i.e. if the setting hasn't been set).
+ return Settings.Global.getInt(AppGlobals.getInitialApplication().getContentResolver(),
+ Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, 1) == 1;
+ }
+
+ @Override
+ public void enableFallbackLogic(boolean enable) {
+ Settings.Global.putInt(AppGlobals.getInitialApplication().getContentResolver(),
+ Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, enable ? 1 : 0);
+ }
+
+ @Override
+ public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) {
+ enablePackageForAllUsers(context, packageName, false);
+ try {
+ PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+ if (pm.getApplicationInfo(packageName, 0).isUpdatedSystemApp()) {
+ pm.deletePackage(packageName, new IPackageDeleteObserver.Stub() {
+ public void packageDeleted(String packageName, int returnCode) {
+ enablePackageForAllUsers(context, packageName, false);
+ }
+ }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
+ }
+ } catch (NameNotFoundException e) {
+ }
+ }
+
+ @Override
+ public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
+ UserManager userManager = (UserManager)context.getSystemService(Context.USER_SERVICE);
+ for(UserInfo userInfo : userManager.getUsers()) {
+ enablePackageForUser(packageName, enable, userInfo.id);
+ }
+ }
+
+ @Override
+ public void enablePackageForUser(String packageName, boolean enable, int userId) {
+ try {
+ AppGlobals.getPackageManager().setApplicationEnabledSetting(
+ packageName,
+ enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0,
+ userId, null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Tried to disable " + packageName + " for user " + userId + ": " + e);
+ }
+ }
+
+ @Override
+ public boolean systemIsDebuggable() {
+ return Build.IS_DEBUGGABLE;
+ }
+
+ @Override
+ public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
+ throws NameNotFoundException {
+ PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+ return pm.getPackageInfo(configInfo.packageName, PACKAGE_FLAGS);
+ }
+
+ // flags declaring we want extra info from the package manager for webview providers
+ private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
+ | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUtilityInterface.java b/services/core/java/com/android/server/webkit/SystemInterface.java
index 1919f400c29a..7bde37a5a4fd 100644
--- a/services/core/java/com/android/server/webkit/WebViewUtilityInterface.java
+++ b/services/core/java/com/android/server/webkit/SystemInterface.java
@@ -16,22 +16,36 @@
package com.android.server.webkit;
-import android.webkit.WebViewProviderInfo;
import android.content.Context;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.webkit.WebViewProviderInfo;
/**
- * Utility interface for the WebViewUpdateService.
+ * System interface for the WebViewUpdateService.
* This interface provides a way to test the WebView preparation mechanism - during normal use this
* interface is implemented using calls to the Android framework, but by providing an alternative
* implementation we can test the WebView preparation logic without reaching other framework code.
+ *
* @hide
*/
-public interface WebViewUtilityInterface {
+public interface SystemInterface {
public WebViewProviderInfo[] getWebViewPackages();
public int onWebViewProviderChanged(PackageInfo packageInfo);
+ public int getFactoryPackageVersion(String packageName) throws NameNotFoundException;
public String getUserChosenWebViewProvider(Context context);
public void updateUserSetting(Context context, String newProviderName);
public void killPackageDependents(String packageName);
+
+ public boolean isFallbackLogicEnabled();
+ public void enableFallbackLogic(boolean enable);
+
+ public void uninstallAndDisablePackageForAllUsers(Context context, String packageName);
+ public void enablePackageForAllUsers(Context context, String packageName, boolean enable);
+ public void enablePackageForUser(String packageName, boolean enable, int userId);
+
+ public boolean systemIsDebuggable();
+ public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
+ throws NameNotFoundException;
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index c4f9cc125411..ebec44554210 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -16,30 +16,20 @@
package com.android.server.webkit;
-import android.app.ActivityManagerNative;
-import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageDeleteObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
-import android.content.pm.UserInfo;
import android.os.Binder;
-import android.os.Build;
import android.os.PatternMatcher;
import android.os.Process;
-import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings.Global;
-import android.provider.Settings;
-import android.util.AndroidRuntimeException;
import android.util.Base64;
import android.util.Slog;
import android.webkit.IWebViewUpdateService;
@@ -52,7 +42,6 @@ import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Iterator;
import java.util.List;
/**
@@ -62,26 +51,21 @@ import java.util.List;
public class WebViewUpdateService extends SystemService {
private static final String TAG = "WebViewUpdateService";
- private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000.
- // Keeps track of the number of running relro creations
- private int mNumRelroCreationsStarted = 0;
- private int mNumRelroCreationsFinished = 0;
- // Implies that we need to rerun relro creation because we are using an out-of-date package
- private boolean mWebViewPackageDirty = false;
- private boolean mAnyWebViewInstalled = false;
-
- private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
+ private BroadcastReceiver mWebViewUpdatedReceiver;
+ private SystemInterface mSystemInterface;
- // The WebView package currently in use (or the one we are preparing).
- private PackageInfo mCurrentWebViewPackage = null;
+ static final int PACKAGE_CHANGED = 0;
+ static final int PACKAGE_ADDED = 1;
+ static final int PACKAGE_ADDED_REPLACED = 2;
+ static final int PACKAGE_REMOVED = 3;
- private BroadcastReceiver mWebViewUpdatedReceiver;
- private WebViewUtilityInterface mWebViewUtility;
+ private WebViewUpdater mWebViewUpdater;
public WebViewUpdateService(Context context) {
super(context);
- mWebViewUtility = new WebViewUtilityImpl();
+ mSystemInterface = new SystemImpl();
+ mWebViewUpdater = new WebViewUpdater(getContext(), mSystemInterface);
}
@Override
@@ -89,76 +73,34 @@ public class WebViewUpdateService extends SystemService {
mWebViewUpdatedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- // When a package is replaced we will receive two intents, one representing
- // the removal of the old package and one representing the addition of the
- // new package.
- // In the case where we receive an intent to remove the old version of the
- // package that is being replaced we early-out here so that we don't run the
- // update-logic twice.
- if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)
- && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
- return;
- }
-
- // Ensure that we only heed PACKAGE_CHANGED intents if they change an entire
- // package, not just a component
- if (intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED)) {
- if (!WebViewFactory.entirePackageChanged(intent)) {
- return;
- }
- }
-
- if (intent.getAction().equals(Intent.ACTION_USER_ADDED)) {
- int userId =
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
- handleNewUser(userId);
- return;
- }
-
- updateFallbackState(context, intent);
-
- for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) {
- String webviewPackage = "package:" + provider.packageName;
-
- if (webviewPackage.equals(intent.getDataString())) {
- boolean updateWebView = false;
- boolean removedOrChangedOldPackage = false;
- String oldProviderName = null;
- PackageInfo newPackage = null;
- synchronized(WebViewUpdateService.this) {
- try {
- newPackage = findPreferredWebViewPackage();
- if (mCurrentWebViewPackage != null)
- oldProviderName = mCurrentWebViewPackage.packageName;
- // Only trigger update actions if the updated package is the one
- // that will be used, or the one that was in use before the
- // update, or if we haven't seen a valid WebView package before.
- updateWebView =
- provider.packageName.equals(newPackage.packageName)
- || provider.packageName.equals(oldProviderName)
- || mCurrentWebViewPackage == null;
- // We removed the old package if we received an intent to remove
- // or replace the old package.
- removedOrChangedOldPackage =
- provider.packageName.equals(oldProviderName);
- if (updateWebView) {
- onWebViewProviderChanged(newPackage);
- }
- } catch (WebViewFactory.MissingWebViewPackageException e) {
- Slog.e(TAG, "Could not find valid WebView package to create " +
- "relro with " + e);
- }
+ switch (intent.getAction()) {
+ case Intent.ACTION_PACKAGE_REMOVED:
+ // When a package is replaced we will receive two intents, one
+ // representing the removal of the old package and one representing the
+ // addition of the new package.
+ // In the case where we receive an intent to remove the old version of
+ // the package that is being replaced we early-out here so that we don't
+ // run the update-logic twice.
+ if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return;
+ packageStateChanged(packageNameFromIntent(intent), PACKAGE_REMOVED);
+ break;
+ case Intent.ACTION_PACKAGE_CHANGED:
+ // Ensure that we only heed PACKAGE_CHANGED intents if they change an
+ // entire package, not just a component
+ if (entirePackageChanged(intent)) {
+ packageStateChanged(packageNameFromIntent(intent), PACKAGE_CHANGED);
}
- if(updateWebView && !removedOrChangedOldPackage
- && oldProviderName != null) {
- // If the provider change is the result of adding or replacing a
- // package that was not the previous provider then we must kill
- // packages dependent on the old package ourselves. The framework
- // only kills dependents of packages that are being removed.
- mWebViewUtility.killPackageDependents(oldProviderName);
- }
- return;
- }
+ break;
+ case Intent.ACTION_PACKAGE_ADDED:
+ packageStateChanged(packageNameFromIntent(intent),
+ (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)
+ ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED));
+ break;
+ case Intent.ACTION_USER_ADDED:
+ int userId =
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ handleNewUser(userId);
+ break;
}
}
};
@@ -168,7 +110,7 @@ public class WebViewUpdateService extends SystemService {
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
// Make sure we only receive intents for WebView packages from our config file.
- for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) {
+ for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
}
getContext().registerReceiver(mWebViewUpdatedReceiver, filter);
@@ -180,12 +122,27 @@ public class WebViewUpdateService extends SystemService {
publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
}
+ private void packageStateChanged(String packageName, int changedState) {
+ updateFallbackState(packageName, changedState);
+ mWebViewUpdater.packageStateChanged(packageName, changedState);
+ }
+
+ public void prepareWebViewInSystemServer() {
+ updateFallbackStateOnBoot();
+ mWebViewUpdater.prepareWebViewInSystemServer();
+ }
+
+ private static String packageNameFromIntent(Intent intent) {
+ return intent.getDataString().substring("package:".length());
+ }
+
private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
for (WebViewProviderInfo provider : providers) {
if (provider.availableByDefault && !provider.isFallback) {
try {
- PackageInfo packageInfo = getPackageInfoForProvider(provider);
- if (isEnabledPackage(packageInfo) && isValidProvider(provider, packageInfo)) {
+ PackageInfo packageInfo = mSystemInterface.getPackageInfoForProvider(provider);
+ if (isEnabledPackage(packageInfo)
+ && mWebViewUpdater.isValidProvider(provider, packageInfo)) {
return true;
}
} catch (NameNotFoundException e) {
@@ -196,59 +153,51 @@ public class WebViewUpdateService extends SystemService {
return false;
}
- private static void enablePackageForUser(String packageName, boolean enable, int userId) {
- try {
- AppGlobals.getPackageManager().setApplicationEnabledSetting(
- packageName,
- enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0,
- userId, null);
- } catch (RemoteException e) {
- Slog.w(TAG, "Tried to disable " + packageName + " for user " + userId + ": " + e);
- }
- }
-
/**
* Called when a new user has been added to update the state of its fallback package.
*/
void handleNewUser(int userId) {
- if (!isFallbackLogicEnabled()) return;
+ if (!mSystemInterface.isFallbackLogicEnabled()) return;
- WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages();
+ WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
if (fallbackProvider == null) return;
- enablePackageForUser(fallbackProvider.packageName,
+ mSystemInterface.enablePackageForUser(fallbackProvider.packageName,
!existsValidNonFallbackProvider(webviewProviders), userId);
}
+ public void updateFallbackStateOnBoot() {
+ WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
+ updateFallbackState(webviewProviders, true);
+ }
+
/**
* Handle the enabled-state of our fallback package, i.e. if there exists some non-fallback
* package that is valid (and available by default) then disable the fallback package,
* otherwise, enable the fallback package.
*/
- void updateFallbackState(final Context context, final Intent intent) {
- if (!isFallbackLogicEnabled()) return;
-
- WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages();
-
- if (intent != null && (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)
- || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED))) {
- // A package was changed / updated / downgraded, early out if it is not one of the
- // webview packages that are available by default.
- String changedPackage = null;
- for (WebViewProviderInfo provider : webviewProviders) {
- String webviewPackage = "package:" + provider.packageName;
- if (webviewPackage.equals(intent.getDataString())) {
- if (provider.availableByDefault) {
- changedPackage = provider.packageName;
- }
- break;
+ public void updateFallbackState(String changedPackage, int changedState) {
+ if (!mSystemInterface.isFallbackLogicEnabled()) return;
+
+ WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
+
+ // A package was changed / updated / downgraded, early out if it is not one of the
+ // webview packages that are available by default.
+ boolean changedPackageAvailableByDefault = false;
+ for (WebViewProviderInfo provider : webviewProviders) {
+ if (provider.packageName.equals(changedPackage)) {
+ if (provider.availableByDefault) {
+ changedPackageAvailableByDefault = true;
}
+ break;
}
- if (changedPackage == null) return;
}
+ if (!changedPackageAvailableByDefault) return;
+ updateFallbackState(webviewProviders, false);
+ }
+ private void updateFallbackState(WebViewProviderInfo[] webviewProviders, boolean isBoot) {
// If there exists a valid and enabled non-fallback package - disable the fallback
// package, otherwise, enable it.
WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
@@ -257,55 +206,29 @@ public class WebViewUpdateService extends SystemService {
boolean isFallbackEnabled = false;
try {
- isFallbackEnabled = isEnabledPackage(getPackageInfoForProvider(fallbackProvider));
+ isFallbackEnabled = isEnabledPackage(
+ mSystemInterface.getPackageInfoForProvider(fallbackProvider));
} catch (NameNotFoundException e) {
}
if (existsValidNonFallbackProvider
// During an OTA the primary user's WebView state might differ from other users', so
// ignore the state of that user during boot.
- && (isFallbackEnabled || intent == null)) {
- // Uninstall and disable fallback package for all users.
- context.getPackageManager().deletePackage(fallbackProvider.packageName,
- new IPackageDeleteObserver.Stub() {
- public void packageDeleted(String packageName, int returnCode) {
- // Ignore returnCode since the deletion could fail, e.g. we might be trying
- // to delete a non-updated system-package (and we should still disable the
- // package)
- UserManager userManager =
- (UserManager)context.getSystemService(Context.USER_SERVICE);
- // Disable the fallback package for all users.
- for(UserInfo userInfo : userManager.getUsers()) {
- enablePackageForUser(packageName, false, userInfo.id);
- }
- }
- }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
+ && (isFallbackEnabled || isBoot)) {
+ mSystemInterface.uninstallAndDisablePackageForAllUsers(getContext(),
+ fallbackProvider.packageName);
} else if (!existsValidNonFallbackProvider
// During an OTA the primary user's WebView state might differ from other users', so
// ignore the state of that user during boot.
- && (!isFallbackEnabled || intent==null)) {
+ && (!isFallbackEnabled || isBoot)) {
// Enable the fallback package for all users.
- UserManager userManager =
- (UserManager)context.getSystemService(Context.USER_SERVICE);
- for(UserInfo userInfo : userManager.getUsers()) {
- enablePackageForUser(fallbackProvider.packageName, true, userInfo.id);
- }
+ mSystemInterface.enablePackageForAllUsers(getContext(),
+ fallbackProvider.packageName, true);
}
}
- private static boolean isFallbackLogicEnabled() {
- // Note that this is enabled by default (i.e. if the setting hasn't been set).
- return Settings.Global.getInt(AppGlobals.getInitialApplication().getContentResolver(),
- Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, 1) == 1;
- }
-
- private static void enableFallbackLogic(boolean enable) {
- Settings.Global.putInt(AppGlobals.getInitialApplication().getContentResolver(),
- Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, enable ? 1 : 0);
- }
-
/**
- * Returns the only fallback provider, or null if there is none.
+ * Returns the only fallback provider in the set of given packages, or null if there is none.
*/
private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) {
for (WebViewProviderInfo provider : webviewPackages) {
@@ -317,188 +240,372 @@ public class WebViewUpdateService extends SystemService {
}
private boolean isFallbackPackage(String packageName) {
- if (packageName == null || !isFallbackLogicEnabled()) return false;
+ if (packageName == null || !mSystemInterface.isFallbackLogicEnabled()) return false;
- WebViewProviderInfo[] webviewPackages = mWebViewUtility.getWebViewPackages();
+ WebViewProviderInfo[] webviewPackages = mSystemInterface.getWebViewPackages();
WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages);
return (fallbackProvider != null
&& packageName.equals(fallbackProvider.packageName));
}
/**
- * Perform any WebView loading preparations that must happen at boot from the system server,
- * after the package manager has started or after an update to the webview is installed.
- * This must be called in the system server.
- * Currently, this means spawning the child processes which will create the relro files.
+ * Class that decides what WebView implementation to use and prepares that implementation for
+ * use.
*/
- public void prepareWebViewInSystemServer() {
- updateFallbackState(getContext(), null);
- try {
- synchronized(this) {
- mCurrentWebViewPackage = findPreferredWebViewPackage();
- onWebViewProviderChanged(mCurrentWebViewPackage);
- }
- } catch (Throwable t) {
- // Log and discard errors at this stage as we must not crash the system server.
- Slog.e(TAG, "error preparing webview provider from system server", t);
+ private static class WebViewUpdater {
+ private Context mContext;
+ private SystemInterface mSystemInterface;
+ private int mMinimumVersionCode = -1;
+
+ public WebViewUpdater(Context context, SystemInterface systemInterface) {
+ mContext = context;
+ mSystemInterface = systemInterface;
}
- }
-
- /**
- * Change WebView provider and provider setting and kill packages using the old provider.
- * Return the new provider (in case we are in the middle of creating relro files this new
- * provider will not be in use directly, but will when the relros are done).
- */
- private String changeProviderAndSetting(String newProviderName) {
- PackageInfo oldPackage = null;
- PackageInfo newPackage = null;
- synchronized(this) {
- oldPackage = mCurrentWebViewPackage;
- mWebViewUtility.updateUserSetting(getContext(), newProviderName);
+ private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000.
+
+ // Keeps track of the number of running relro creations
+ private int mNumRelroCreationsStarted = 0;
+ private int mNumRelroCreationsFinished = 0;
+ // Implies that we need to rerun relro creation because we are using an out-of-date package
+ private boolean mWebViewPackageDirty = false;
+ private boolean mAnyWebViewInstalled = false;
+
+ private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
+
+ // The WebView package currently in use (or the one we are preparing).
+ private PackageInfo mCurrentWebViewPackage = null;
+
+ private Object mLock = new Object();
+
+ public void packageStateChanged(String packageName, int changedState) {
+ for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+ String webviewPackage = provider.packageName;
+
+ if (webviewPackage.equals(packageName)) {
+ boolean updateWebView = false;
+ boolean removedOrChangedOldPackage = false;
+ String oldProviderName = null;
+ PackageInfo newPackage = null;
+ synchronized(mLock) {
+ try {
+ newPackage = findPreferredWebViewPackage();
+ if (mCurrentWebViewPackage != null)
+ oldProviderName = mCurrentWebViewPackage.packageName;
+ // Only trigger update actions if the updated package is the one
+ // that will be used, or the one that was in use before the
+ // update, or if we haven't seen a valid WebView package before.
+ updateWebView =
+ provider.packageName.equals(newPackage.packageName)
+ || provider.packageName.equals(oldProviderName)
+ || mCurrentWebViewPackage == null;
+ // We removed the old package if we received an intent to remove
+ // or replace the old package.
+ removedOrChangedOldPackage =
+ provider.packageName.equals(oldProviderName);
+ if (updateWebView) {
+ onWebViewProviderChanged(newPackage);
+ }
+ } catch (WebViewFactory.MissingWebViewPackageException e) {
+ Slog.e(TAG, "Could not find valid WebView package to create " +
+ "relro with " + e);
+ }
+ }
+ if(updateWebView && !removedOrChangedOldPackage
+ && oldProviderName != null) {
+ // If the provider change is the result of adding or replacing a
+ // package that was not the previous provider then we must kill
+ // packages dependent on the old package ourselves. The framework
+ // only kills dependents of packages that are being removed.
+ mSystemInterface.killPackageDependents(oldProviderName);
+ }
+ return;
+ }
+ }
+ }
+ public void prepareWebViewInSystemServer() {
try {
- newPackage = findPreferredWebViewPackage();
- if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) {
- // If we don't perform the user change, revert the settings change.
- mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName);
- return newPackage.packageName;
+ synchronized(mLock) {
+ mCurrentWebViewPackage = findPreferredWebViewPackage();
+ onWebViewProviderChanged(mCurrentWebViewPackage);
}
- } catch (WebViewFactory.MissingWebViewPackageException e) {
- Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView package "
- + e);
- // If we don't perform the user change but don't have an installed WebView package,
- // we will have changed the setting and it will be used when a package is available.
- return newProviderName;
+ } catch (Throwable t) {
+ // Log and discard errors at this stage as we must not crash the system server.
+ Slog.e(TAG, "error preparing webview provider from system server", t);
}
- onWebViewProviderChanged(newPackage);
}
- // Kill apps using the old provider
- if (oldPackage != null) {
- mWebViewUtility.killPackageDependents(oldPackage.packageName);
+
+ /**
+ * Change WebView provider and provider setting and kill packages using the old provider.
+ * Return the new provider (in case we are in the middle of creating relro files this new
+ * provider will not be in use directly, but will when the relros are done).
+ */
+ public String changeProviderAndSetting(String newProviderName) {
+ PackageInfo oldPackage = null;
+ PackageInfo newPackage = null;
+ synchronized(mLock) {
+ oldPackage = mCurrentWebViewPackage;
+ mSystemInterface.updateUserSetting(mContext, newProviderName);
+
+ try {
+ newPackage = findPreferredWebViewPackage();
+ if (oldPackage != null
+ && newPackage.packageName.equals(oldPackage.packageName)) {
+ // If we don't perform the user change, revert the settings change.
+ mSystemInterface.updateUserSetting(mContext, newPackage.packageName);
+ return newPackage.packageName;
+ }
+ } catch (WebViewFactory.MissingWebViewPackageException e) {
+ Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView " +
+ "package " + e);
+ // If we don't perform the user change but don't have an installed WebView
+ // package, we will have changed the setting and it will be used when a package
+ // is available.
+ return newProviderName;
+ }
+ onWebViewProviderChanged(newPackage);
+ }
+ // Kill apps using the old provider
+ if (oldPackage != null) {
+ mSystemInterface.killPackageDependents(oldPackage.packageName);
+ }
+ return newPackage.packageName;
}
- return newPackage.packageName;
- }
- /**
- * This is called when we change WebView provider, either when the current provider is updated
- * or a new provider is chosen / takes precedence.
- */
- private void onWebViewProviderChanged(PackageInfo newPackage) {
- synchronized(this) {
- mAnyWebViewInstalled = true;
- if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
- mCurrentWebViewPackage = newPackage;
- mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName);
-
- // The relro creations might 'finish' (not start at all) before
- // WebViewFactory.onWebViewProviderChanged which means we might not know the number
- // of started creations before they finish.
- mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
- mNumRelroCreationsFinished = 0;
- mNumRelroCreationsStarted = mWebViewUtility.onWebViewProviderChanged(newPackage);
- // If the relro creations finish before we know the number of started creations we
- // will have to do any cleanup/notifying here.
- checkIfRelrosDoneLocked();
- } else {
- mWebViewPackageDirty = true;
+ /**
+ * This is called when we change WebView provider, either when the current provider is
+ * updated or a new provider is chosen / takes precedence.
+ */
+ private void onWebViewProviderChanged(PackageInfo newPackage) {
+ synchronized(mLock) {
+ mAnyWebViewInstalled = true;
+ if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+ mCurrentWebViewPackage = newPackage;
+ mSystemInterface.updateUserSetting(mContext, newPackage.packageName);
+
+ // The relro creations might 'finish' (not start at all) before
+ // WebViewFactory.onWebViewProviderChanged which means we might not know the
+ // number of started creations before they finish.
+ mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
+ mNumRelroCreationsFinished = 0;
+ mNumRelroCreationsStarted =
+ mSystemInterface.onWebViewProviderChanged(newPackage);
+ // If the relro creations finish before we know the number of started creations
+ // we will have to do any cleanup/notifying here.
+ checkIfRelrosDoneLocked();
+ } else {
+ mWebViewPackageDirty = true;
+ }
}
}
- }
- private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
- WebViewProviderInfo[] allProviders = mWebViewUtility.getWebViewPackages();
- List<ProviderAndPackageInfo> providers = new ArrayList<>();
- for(int n = 0; n < allProviders.length; n++) {
- try {
- PackageInfo packageInfo = getPackageInfoForProvider(allProviders[n]);
- if (isValidProvider(allProviders[n], packageInfo)) {
- providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
+ private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
+ WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
+ List<ProviderAndPackageInfo> providers = new ArrayList<>();
+ for(int n = 0; n < allProviders.length; n++) {
+ try {
+ PackageInfo packageInfo =
+ mSystemInterface.getPackageInfoForProvider(allProviders[n]);
+ if (isValidProvider(allProviders[n], packageInfo)) {
+ providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
+ }
+ } catch (NameNotFoundException e) {
+ // Don't add non-existent packages
}
- } catch (NameNotFoundException e) {
- // Don't add non-existent packages
}
+ return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
}
- return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
- }
- /**
- * Fetch only the currently valid WebView packages.
- **/
- private WebViewProviderInfo[] getValidWebViewPackages() {
- ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
- WebViewProviderInfo[] providers = new WebViewProviderInfo[providersAndPackageInfos.length];
- for(int n = 0; n < providersAndPackageInfos.length; n++) {
- providers[n] = providersAndPackageInfos[n].provider;
- }
- return providers;
- }
+ /**
+ * Fetch only the currently valid WebView packages.
+ **/
+ public WebViewProviderInfo[] getValidWebViewPackages() {
+ ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
+ WebViewProviderInfo[] providers =
+ new WebViewProviderInfo[providersAndPackageInfos.length];
+ for(int n = 0; n < providersAndPackageInfos.length; n++) {
+ providers[n] = providersAndPackageInfos[n].provider;
+ }
+ return providers;
+ }
- private class ProviderAndPackageInfo {
- public final WebViewProviderInfo provider;
- public final PackageInfo packageInfo;
- public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
- this.provider = provider;
- this.packageInfo = packageInfo;
+ private class ProviderAndPackageInfo {
+ public final WebViewProviderInfo provider;
+ public final PackageInfo packageInfo;
+
+ public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
+ this.provider = provider;
+ this.packageInfo = packageInfo;
+ }
}
- }
- /**
- * Returns either the package info of the WebView provider determined in the following way:
- * If the user has chosen a provider then use that if it is valid,
- * otherwise use the first package in the webview priority list that is valid.
- *
- * @hide
- */
- private PackageInfo findPreferredWebViewPackage() {
- ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
+ /**
+ * Returns either the package info of the WebView provider determined in the following way:
+ * If the user has chosen a provider then use that if it is valid,
+ * otherwise use the first package in the webview priority list that is valid.
+ *
+ */
+ private PackageInfo findPreferredWebViewPackage() {
+ ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
- String userChosenProvider = mWebViewUtility.getUserChosenWebViewProvider(getContext());
+ String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext);
- // If the user has chosen provider, use that
- for (ProviderAndPackageInfo providerAndPackage : providers) {
- if (providerAndPackage.provider.packageName.equals(userChosenProvider)
- && isEnabledPackage(providerAndPackage.packageInfo)) {
+ // If the user has chosen provider, use that
+ for (ProviderAndPackageInfo providerAndPackage : providers) {
+ if (providerAndPackage.provider.packageName.equals(userChosenProvider)
+ && isEnabledPackage(providerAndPackage.packageInfo)) {
+ return providerAndPackage.packageInfo;
+ }
+ }
+
+ // User did not choose, or the choice failed; use the most stable provider that is
+ // enabled and available by default (not through user choice).
+ for (ProviderAndPackageInfo providerAndPackage : providers) {
+ if (providerAndPackage.provider.availableByDefault
+ && isEnabledPackage(providerAndPackage.packageInfo)) {
+ return providerAndPackage.packageInfo;
+ }
+ }
+
+ // Could not find any enabled package either, use the most stable provider.
+ for (ProviderAndPackageInfo providerAndPackage : providers) {
return providerAndPackage.packageInfo;
}
+
+ mAnyWebViewInstalled = false;
+ throw new WebViewFactory.MissingWebViewPackageException(
+ "Could not find a loadable WebView package");
}
- // User did not choose, or the choice failed; use the most stable provider that is
- // enabled and available by default (not through user choice).
- for (ProviderAndPackageInfo providerAndPackage : providers) {
- if (providerAndPackage.provider.availableByDefault
- && isEnabledPackage(providerAndPackage.packageInfo)) {
- return providerAndPackage.packageInfo;
+ public void notifyRelroCreationCompleted() {
+ synchronized (mLock) {
+ mNumRelroCreationsFinished++;
+ checkIfRelrosDoneLocked();
}
}
- // Could not find any enabled package either, use the most stable provider.
- for (ProviderAndPackageInfo providerAndPackage : providers) {
- return providerAndPackage.packageInfo;
+ public WebViewProviderResponse waitForAndGetProvider() {
+ PackageInfo webViewPackage = null;
+ final long NS_PER_MS = 1000000;
+ final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
+ boolean webViewReady = false;
+ int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
+ synchronized (mLock) {
+ webViewReady = webViewIsReadyLocked();
+ while (!webViewReady) {
+ final long timeNowMs = System.nanoTime() / NS_PER_MS;
+ if (timeNowMs >= timeoutTimeMs) break;
+ try {
+ mLock.wait(timeoutTimeMs - timeNowMs);
+ } catch (InterruptedException e) {}
+ webViewReady = webViewIsReadyLocked();
+ }
+ // Make sure we return the provider that was used to create the relro file
+ webViewPackage = mCurrentWebViewPackage;
+ if (webViewReady) {
+ } else if (!mAnyWebViewInstalled) {
+ webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+ } else {
+ // Either the current relro creation isn't done yet, or the new relro creatioin
+ // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
+ webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
+ }
+ }
+ if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
+ return new WebViewProviderResponse(webViewPackage, webViewStatus);
}
- mAnyWebViewInstalled = false;
- throw new WebViewFactory.MissingWebViewPackageException(
- "Could not find a loadable WebView package");
- }
+ public String getCurrentWebViewPackageName() {
+ synchronized(mLock) {
+ if (mCurrentWebViewPackage == null)
+ return null;
+ return mCurrentWebViewPackage.packageName;
+ }
+ }
- /**
- * Returns whether this provider is valid for use as a WebView provider.
- */
- private static boolean isValidProvider(WebViewProviderInfo configInfo,
- PackageInfo packageInfo) {
- if (providerHasValidSignature(configInfo, packageInfo) &&
- WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) {
- return true;
+ /**
+ * Returns whether WebView is ready and is not going to go through its preparation phase
+ * again directly.
+ */
+ private boolean webViewIsReadyLocked() {
+ return !mWebViewPackageDirty
+ && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
+ // The current package might be replaced though we haven't received an intent
+ // declaring this yet, the following flag makes anyone loading WebView to wait in
+ // this case.
+ && mAnyWebViewInstalled;
+ }
+
+ private void checkIfRelrosDoneLocked() {
+ if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+ if (mWebViewPackageDirty) {
+ mWebViewPackageDirty = false;
+ // If we have changed provider since we started the relro creation we need to
+ // redo the whole process using the new package instead.
+ PackageInfo newPackage = findPreferredWebViewPackage();
+ onWebViewProviderChanged(newPackage);
+ } else {
+ mLock.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Returns whether this provider is valid for use as a WebView provider.
+ */
+ public boolean isValidProvider(WebViewProviderInfo configInfo,
+ PackageInfo packageInfo) {
+ if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+ && packageInfo.versionCode < getMinimumVersionCode()
+ && !mSystemInterface.systemIsDebuggable()) {
+ // Non-system package webview providers may be downgraded arbitrarily low, prevent
+ // that by enforcing minimum version code. This check is only enforced for user
+ // builds.
+ return false;
+ }
+ if (providerHasValidSignature(configInfo, packageInfo, mSystemInterface) &&
+ WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the minimum version code allowed for a valid provider. It is the minimum versionCode
+ * of all available-by-default and non-fallback WebView provider packages. If there is no
+ * such WebView provider package on the system, then return -1, which means all positive
+ * versionCode WebView packages are accepted.
+ */
+ private int getMinimumVersionCode() {
+ if (mMinimumVersionCode > 0) {
+ return mMinimumVersionCode;
+ }
+
+ for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+ if (provider.availableByDefault && !provider.isFallback) {
+ try {
+ int versionCode =
+ mSystemInterface.getFactoryPackageVersion(provider.packageName);
+ if (mMinimumVersionCode < 0 || versionCode < mMinimumVersionCode) {
+ mMinimumVersionCode = versionCode;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // Safe to ignore.
+ }
+ }
+ }
+
+ return mMinimumVersionCode;
}
- return false;
}
private static boolean providerHasValidSignature(WebViewProviderInfo provider,
- PackageInfo packageInfo) {
- if (Build.IS_DEBUGGABLE)
+ PackageInfo packageInfo, SystemInterface systemInterface) {
+ if (systemInterface.systemIsDebuggable()) {
return true;
+ }
Signature[] packageSignatures;
// If no signature is declared, instead check whether the package is included in the
// system.
@@ -527,40 +634,16 @@ public class WebViewUpdateService extends SystemService {
return packageInfo.applicationInfo.enabled;
}
- private static PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
- throws NameNotFoundException {
- PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
- return pm.getPackageInfo(configInfo.packageName, PACKAGE_FLAGS);
- }
-
- // flags declaring we want extra info from the package manager for webview providers
- private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
-
/**
- * Returns whether WebView is ready and is not going to go through its preparation phase again
- * directly.
+ * Returns whether the entire package from an ACTION_PACKAGE_CHANGED intent was changed (rather
+ * than just one of its components).
+ * @hide
*/
- private boolean webViewIsReadyLocked() {
- return !mWebViewPackageDirty
- && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
- // The current package might be replaced though we haven't received an intent declaring
- // this yet, the following flag makes anyone loading WebView to wait in this case.
- && mAnyWebViewInstalled;
- }
-
- private void checkIfRelrosDoneLocked() {
- if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
- if (mWebViewPackageDirty) {
- mWebViewPackageDirty = false;
- // If we have changed provider since we started the relro creation we need to
- // redo the whole process using the new package instead.
- PackageInfo newPackage = findPreferredWebViewPackage();
- onWebViewProviderChanged(newPackage);
- } else {
- this.notifyAll();
- }
- }
+ public static boolean entirePackageChanged(Intent intent) {
+ String[] componentList =
+ intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ return Arrays.asList(componentList).contains(
+ intent.getDataString().substring("package:".length()));
}
private class BinderService extends IWebViewUpdateService.Stub {
@@ -590,10 +673,7 @@ public class WebViewUpdateService extends SystemService {
long callingId = Binder.clearCallingIdentity();
try {
- synchronized (WebViewUpdateService.this) {
- mNumRelroCreationsFinished++;
- checkIfRelrosDoneLocked();
- }
+ WebViewUpdateService.this.mWebViewUpdater.notifyRelroCreationCompleted();
} finally {
Binder.restoreCallingIdentity(callingId);
}
@@ -613,34 +693,7 @@ public class WebViewUpdateService extends SystemService {
throw new IllegalStateException("Cannot create a WebView from the SystemServer");
}
- PackageInfo webViewPackage = null;
- final long NS_PER_MS = 1000000;
- final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
- boolean webViewReady = false;
- int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
- synchronized (WebViewUpdateService.this) {
- webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
- while (!webViewReady) {
- final long timeNowMs = System.nanoTime() / NS_PER_MS;
- if (timeNowMs >= timeoutTimeMs) break;
- try {
- WebViewUpdateService.this.wait(timeoutTimeMs - timeNowMs);
- } catch (InterruptedException e) {}
- webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
- }
- // Make sure we return the provider that was used to create the relro file
- webViewPackage = WebViewUpdateService.this.mCurrentWebViewPackage;
- if (webViewReady) {
- } else if (!mAnyWebViewInstalled) {
- webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
- } else {
- // Either the current relro creation isn't done yet, or the new relro creatioin
- // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
- webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
- }
- }
- if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
- return new WebViewProviderResponse(webViewPackage, webViewStatus);
+ return WebViewUpdateService.this.mWebViewUpdater.waitForAndGetProvider();
}
/**
@@ -659,26 +712,28 @@ public class WebViewUpdateService extends SystemService {
throw new SecurityException(msg);
}
- return WebViewUpdateService.this.changeProviderAndSetting(newProvider);
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ return WebViewUpdateService.this.mWebViewUpdater.changeProviderAndSetting(
+ newProvider);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
}
@Override // Binder call
public WebViewProviderInfo[] getValidWebViewPackages() {
- return WebViewUpdateService.this.getValidWebViewPackages();
+ return WebViewUpdateService.this.mWebViewUpdater.getValidWebViewPackages();
}
@Override // Binder call
public WebViewProviderInfo[] getAllWebViewPackages() {
- return WebViewUpdateService.this.mWebViewUtility.getWebViewPackages();
+ return WebViewUpdateService.this.mSystemInterface.getWebViewPackages();
}
@Override // Binder call
public String getCurrentWebViewPackageName() {
- synchronized(WebViewUpdateService.this) {
- if (WebViewUpdateService.this.mCurrentWebViewPackage == null)
- return null;
- return WebViewUpdateService.this.mCurrentWebViewPackage.packageName;
- }
+ return WebViewUpdateService.this.mWebViewUpdater.getCurrentWebViewPackageName();
}
@Override // Binder call
@@ -699,7 +754,7 @@ public class WebViewUpdateService extends SystemService {
throw new SecurityException(msg);
}
- WebViewUpdateService.enableFallbackLogic(enable);
+ WebViewUpdateService.this.mSystemInterface.enableFallbackLogic(enable);
}
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
index a9461e82a596..68448f30b82d 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
@@ -36,12 +36,13 @@ class WebViewUpdateServiceShellCommand extends ShellCommand {
final PrintWriter pw = getOutPrintWriter();
try {
- // TODO(gsennton) add command for changing WebView provider
switch(cmd) {
case "enable-redundant-packages":
return enableFallbackLogic(false);
case "disable-redundant-packages":
return enableFallbackLogic(true);
+ case "set-webview-implementation":
+ return setWebViewImplementation();
default:
return handleDefaultCommands(cmd);
}
@@ -58,6 +59,21 @@ class WebViewUpdateServiceShellCommand extends ShellCommand {
return 0;
}
+ private int setWebViewImplementation() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ String shellChosenPackage = getNextArg();
+ String newPackage = mInterface.changeProviderAndSetting(shellChosenPackage);
+ if (shellChosenPackage.equals(newPackage)) {
+ pw.println("Success");
+ return 0;
+ } else {
+ pw.println(String.format(
+ "Failed to switch to %s, the WebView implementation is now provided by %s.",
+ shellChosenPackage, newPackage));
+ return 1;
+ }
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -72,6 +88,8 @@ class WebViewUpdateServiceShellCommand extends ShellCommand {
pw.println(" disable-redundant-packages");
pw.println(" Disallow installing and enabling fallback packages when a more-preferred");
pw.println(" package is available.");
+ pw.println(" set-webview-implementation PACKAGE");
+ pw.println(" Set the WebView implementation to the specified package.");
pw.println();
}
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index b501398c7d57..bae628ab1892 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -39,6 +39,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -1213,6 +1214,8 @@ final class AccessibilityController {
window.type = windowState.mAttrs.type;
window.layer = windowState.mLayer;
window.token = windowState.mClient.asBinder();
+ window.title = windowState.mAttrs.getTitle();
+ window.accessibilityIdOfAnchor = windowState.mAttrs.accessibilityIdOfAnchor;
WindowState attachedWindow = windowState.mAttachedWindow;
if (attachedWindow != null) {
@@ -1285,6 +1288,12 @@ final class AccessibilityController {
&& !oldWindow.childTokens.equals(newWindow.childTokens)) {
return true;
}
+ if (!TextUtils.equals(oldWindow.title, newWindow.title)) {
+ return true;
+ }
+ if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) {
+ return true;
+ }
return false;
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d6842787eef5..11b01ccb9c68 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -881,7 +881,7 @@ public class AppTransition implements Dump {
* when a thumbnail is specified with the pending animation override.
*/
Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets,
- Bitmap thumbnailHeader, final int taskId, int orientation) {
+ Bitmap thumbnailHeader, final int taskId, int uiMode, int orientation) {
Animation a;
final int thumbWidthI = thumbnailHeader.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -896,7 +896,7 @@ public class AppTransition implements Dump {
final float toY;
final float pivotX;
final float pivotY;
- if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ if (isTvUiMode(uiMode) || orientation == Configuration.ORIENTATION_PORTRAIT) {
fromX = mTmpRect.left;
fromY = mTmpRect.top;
@@ -1028,7 +1028,7 @@ public class AppTransition implements Dump {
* activity that is leaving, and the activity that is entering.
*/
Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
- int orientation, int transit, Rect containingFrame, Rect contentInsets,
+ int uiMode, int orientation, int transit, Rect containingFrame, Rect contentInsets,
@Nullable Rect surfaceInsets, boolean freeform, int taskId) {
Animation a;
final int appWidth = containingFrame.width();
@@ -1067,8 +1067,7 @@ public class AppTransition implements Dump {
mTmpFromClipRect.inset(contentInsets);
mNextAppTransitionInsets.set(contentInsets);
- if (orientation == Configuration.ORIENTATION_PORTRAIT) {
- // We scale the width and clip to the top/left square
+ if (isTvUiMode(uiMode) || orientation == Configuration.ORIENTATION_PORTRAIT) {
// We scale the width and clip to the top/left square
float scale = thumbWidth /
(appWidth - contentInsets.left - contentInsets.right);
@@ -1401,7 +1400,7 @@ public class AppTransition implements Dump {
* to the recents thumbnail and hence need to account for the surface being
* bigger.
*/
- Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
+ Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, int uiMode,
int orientation, Rect frame, Rect displayFrame, Rect insets,
@Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform,
int taskId) {
@@ -1481,7 +1480,7 @@ public class AppTransition implements Dump {
mNextAppTransitionScaleUp =
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
a = createAspectScaledThumbnailEnterExitAnimationLocked(
- getThumbnailTransitionState(enter), orientation, transit, frame,
+ getThumbnailTransitionState(enter), uiMode, orientation, transit, frame,
insets, surfaceInsets, freeform, taskId);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
@@ -1922,4 +1921,11 @@ public class AppTransition implements Dump {
}
return prepared;
}
+
+ /**
+ * @return whether the specified {@param uiMode} is the TV mode.
+ */
+ private boolean isTvUiMode(int uiMode) {
+ return (uiMode & Configuration.UI_MODE_TYPE_TELEVISION) > 0;
+ }
}
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 97d0ae0f8546..3ec02b9f66fc 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -183,7 +183,12 @@ class DimLayerController {
for (int i = mState.size() - 1; i >= 0; i--) {
DimLayer.DimLayerUser user = mState.keyAt(i);
- if (user.isFullscreen()) {
+ DimLayerState state = mState.valueAt(i);
+ // We have to check that we are acutally the shared fullscreen layer
+ // for this path. If we began as non fullscreen and became fullscreen
+ // (e.g. Docked stack closing), then we may not be the shared layer
+ // and we have to make sure we always animate the layer.
+ if (user.isFullscreen() && state.dimLayer == mSharedFullScreenDimLayer) {
fullScreen = i;
if (mState.valueAt(i).continueDimming) {
fullScreenAndDimming = i;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 68ea4df0c0b0..6ac71c795ca7 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -76,8 +76,8 @@ public class DockedStackDividerController implements DimLayerUser {
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
- private final int mDividerWindowWidth;
- private final int mDividerInsets;
+ private int mDividerWindowWidth;
+ private int mDividerInsets;
private boolean mResizing;
private WindowState mWindow;
private final Rect mTmpRect = new Rect();
@@ -105,14 +105,23 @@ public class DockedStackDividerController implements DimLayerUser {
mService = service;
mDisplayContent = displayContent;
final Context context = service.mContext;
- mDividerWindowWidth = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_thickness);
- mDividerInsets = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_insets);
mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId(),
"DockedStackDim");
mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
context, android.R.interpolator.fast_out_slow_in);
+ loadDimens();
+ }
+
+ private void loadDimens() {
+ final Context context = mService.mContext;
+ mDividerWindowWidth = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_thickness);
+ mDividerInsets = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_insets);
+ }
+
+ void onConfigurationChanged() {
+ loadDimens();
}
boolean isResizing() {
@@ -243,6 +252,9 @@ public class DockedStackDividerController implements DimLayerUser {
}
}
mDockedStackListeners.finishBroadcast();
+ if (!exists) {
+ setMinimizedDockedStack(false);
+ }
}
void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) {
@@ -263,6 +275,7 @@ public class DockedStackDividerController implements DimLayerUser {
notifyDockedDividerVisibilityChanged(wasVisible());
notifyDockedStackExistsChanged(
mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID) != null);
+ notifyDockedStackMinimizedChanged(mMinimizedDock, 0 /* animDuration */);
}
void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
@@ -338,12 +351,13 @@ public class DockedStackDividerController implements DimLayerUser {
* @param animate Whether to animate the change.
*/
private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
- if (minimizedDock == mMinimizedDock
+ final boolean wasMinimized = mMinimizedDock;
+ mMinimizedDock = minimizedDock;
+ if (minimizedDock == wasMinimized
|| mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
return;
}
- mMinimizedDock = minimizedDock;
mAnimatingForIme = false;
if (minimizedDock) {
if (animate) {
@@ -369,13 +383,13 @@ public class DockedStackDividerController implements DimLayerUser {
private void setMinimizedDockedStack(boolean minimized) {
final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
+ notifyDockedStackMinimizedChanged(minimized, 0);
if (stack == null) {
return;
}
if (stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f)) {
mService.mWindowPlacerLocked.performSurfacePlacement();
}
- notifyDockedStackMinimizedChanged(minimized, 0);
}
private boolean isAnimationMaximizing() {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index eea0ca0666f7..8a9ace780ad5 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -595,6 +595,12 @@ class Task implements DimLayer.DimLayerUser {
if (win.mHasSurface && !resizingWindows.contains(win)) {
if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win);
resizingWindows.add(win);
+
+ // If we are not drag resizing, force recreating of a new surface so updating
+ // the content and positioning that surface will be in sync.
+ if (!win.computeDragResizing()) {
+ win.mResizedWhileNotDragResizing = true;
+ }
}
if (win.isGoneForLayoutLw()) {
win.mResizedWhileGone = true;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index bb0ec4c33049..3430ac9289a5 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -37,8 +37,8 @@ import java.util.ArrayList;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -89,6 +89,9 @@ public class TaskStack implements DimLayer.DimLayerUser,
// Device rotation as of the last time {@link #mBounds} was set.
int mRotation;
+ /** Density as of last time {@link #mBounds} was set. */
+ int mDensity;
+
/** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
DimLayer mAnimationBackgroundSurface;
@@ -250,9 +253,11 @@ public class TaskStack implements DimLayer.DimLayerUser,
private boolean setBounds(Rect bounds) {
boolean oldFullscreen = mFullscreen;
int rotation = Surface.ROTATION_0;
+ int density = DENSITY_DPI_UNDEFINED;
if (mDisplayContent != null) {
mDisplayContent.getLogicalDisplayRect(mTmpRect);
rotation = mDisplayContent.getDisplayInfo().rotation;
+ density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
mFullscreen = bounds == null;
if (mFullscreen) {
bounds = mTmpRect;
@@ -274,6 +279,7 @@ public class TaskStack implements DimLayer.DimLayerUser,
mBounds.set(bounds);
mRotation = rotation;
+ mDensity = density;
updateAdjustedBounds();
@@ -343,20 +349,21 @@ public class TaskStack implements DimLayer.DimLayerUser,
mTmpRect2.set(mBounds);
final int newRotation = mDisplayContent.getDisplayInfo().rotation;
- if (mRotation == newRotation) {
+ final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
+ if (mRotation == newRotation && mDensity == newDensity) {
setBounds(mTmpRect2);
} else {
mLastUpdateDisplayInfoRotation = newRotation;
- updateBoundsAfterRotation(true);
+ updateBoundsAfterConfigChange(true);
}
}
boolean onConfigurationChanged() {
mLastConfigChangedRotation = getDisplayInfo().rotation;
- return updateBoundsAfterRotation(false);
+ return updateBoundsAfterConfigChange(false);
}
- boolean updateBoundsAfterRotation(boolean scheduleResize) {
+ boolean updateBoundsAfterConfigChange(boolean scheduleResize) {
if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) {
// We wait for the rotation values after configuration change and display info. update
// to be equal before updating the bounds due to rotation change otherwise things might
@@ -365,8 +372,9 @@ public class TaskStack implements DimLayer.DimLayerUser,
}
final int newRotation = getDisplayInfo().rotation;
+ final int newDensity = getDisplayInfo().logicalDensityDpi;
- if (mRotation == newRotation) {
+ if (mRotation == newRotation && mDensity == newDensity) {
// Nothing to do here if the rotation didn't change
return false;
}
@@ -957,9 +965,11 @@ public class TaskStack implements DimLayer.DimLayerUser,
(int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
} else if (dockSide == DOCKED_LEFT) {
mTmpAdjustedBounds.set(mBounds);
+ final int width = mBounds.width();
mTmpAdjustedBounds.right =
(int) (minimizeAmount * mDockedStackMinimizeThickness
+ (1 - minimizeAmount) * mBounds.right);
+ mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
} else if (dockSide == DOCKED_RIGHT) {
mTmpAdjustedBounds.set(mBounds);
mTmpAdjustedBounds.left =
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index f76f03fdc0fe..6bdcd42ee081 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -191,18 +191,20 @@ public class WindowLayersController {
}
private void adjustSpecialWindows() {
- int layer = mHighestApplicationLayer + 1;
+ int layer = mHighestApplicationLayer + WINDOW_LAYER_MULTIPLIER;
// For pinned and docked stack window, we want to make them above other windows also when
// these windows are animating.
while (!mDockedWindows.isEmpty()) {
layer = assignAndIncreaseLayerIfNeeded(mDockedWindows.remove(), layer);
}
- // Leave some space here so the dim layer while dismissing docked/fullscreen stack has space
- // below the divider but above the app windows. It needs to be below the divider in because
- // the divider sometimes overlaps the app windows.
- layer++;
layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);
+
+ if (mDockDivider != null && mDockDivider.isVisibleLw()
+ && mService.mInputMethodWindow != null) {
+ layer = assignAndIncreaseLayerIfNeeded(mService.mInputMethodWindow, layer);
+ }
+
// We know that we will be animating a relaunching window in the near future, which will
// receive a z-order increase. We want the replaced window to immediately receive the same
// treatment, e.g. to be above the dock divider.
@@ -216,13 +218,14 @@ public class WindowLayersController {
}
private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
- if (win != null) {
+ if (win != null && layer > win.mLayer) {
assignAnimLayer(win, layer);
- layer++;
+ // Make sure we leave space inbetween normal windows for dims and such.
+ layer += WINDOW_LAYER_MULTIPLIER;
}
return layer;
}
-
+
private void assignAnimLayer(WindowState w, int layer) {
w.mLayer = layer;
w.mWinAnimator.mAnimLayer = w.mLayer + w.getAnimLayerAdjustment() +
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 14ae74f3967d..2af324d19710 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1369,11 +1369,8 @@ public class WindowManagerService extends IWindowManager.Stub
final int fl = w.mAttrs.flags
& (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
final int type = w.mAttrs.type;
- // The dock divider has to sit above the application windows and so does the IME. IME also
- // needs to sit above the dock divider, so it doesn't get cut in half. We make the dock
- // divider be a target for IME, so this relationship can occur naturally.
if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
- || type == TYPE_APPLICATION_STARTING || type == TYPE_DOCK_DIVIDER) {
+ || type == TYPE_APPLICATION_STARTING) {
if (DEBUG_INPUT_METHOD) {
Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
if (!w.isVisibleOrAdding()) {
@@ -2020,7 +2017,13 @@ public class WindowManagerService extends IWindowManager.Stub
final WindowStateAnimator winAnimator = win.mWinAnimator;
winAnimator.mEnterAnimationPending = true;
winAnimator.mEnteringAnimation = true;
- prepareWindowReplacementTransition(atoken);
+ // Check if we need to prepare a transition for replacing window first.
+ if (atoken != null && !prepareWindowReplacementTransition(atoken)) {
+ // If not, check if need to set up a dummy transition during display freeze
+ // so that the unfreeze wait for the apps to draw. This might be needed if
+ // the app is relaunching.
+ prepareNoneTransitionForRelaunching(atoken);
+ }
if (displayContent.isDefaultDisplay) {
if (mPolicy.getInsetHintLw(win.mAttrs, mRotation, outContentInsets, outStableInsets,
@@ -2080,10 +2083,10 @@ public class WindowManagerService extends IWindowManager.Stub
return res;
}
- private void prepareWindowReplacementTransition(AppWindowToken atoken) {
- if (atoken == null) {
- return;
- }
+ /**
+ * Returns true if we're done setting up any transitions.
+ */
+ private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
atoken.allDrawn = false;
WindowState replacedWindow = null;
for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
@@ -2096,7 +2099,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (replacedWindow == null) {
// We expect to already receive a request to remove the old window. If it did not
// happen, let's just simply add a window.
- return;
+ return false;
}
// We use the visible frame, because we want the animation to morph the window from what
// was visible to the user to the final destination of the new window.
@@ -2108,6 +2111,19 @@ public class WindowManagerService extends IWindowManager.Stub
mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
frame.width(), frame.height());
executeAppTransition();
+ return true;
+ }
+
+ private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
+ // Set up a none-transition and add the app to opening apps, so that the display
+ // unfreeze wait for the apps to be drawn.
+ // Note that if the display unfroze already because app unfreeze timed out,
+ // we don't set up the transition anymore and just let it go.
+ if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
+ mOpeningApps.add(atoken);
+ prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
+ executeAppTransition();
+ }
}
/**
@@ -2570,7 +2586,7 @@ public class WindowManagerService extends IWindowManager.Stub
try {
- win.applyGravityAndUpdateFrame();
+ win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame);
win.mWinAnimator.computeShownFrameLocked();
win.mWinAnimator.setSurfaceBoundariesLocked(false);
@@ -2919,8 +2935,9 @@ public class WindowManagerService extends IWindowManager.Stub
// If we're starting a drag-resize, we'll be changing the surface size as well as
// notifying the client to render to with an offset from the surface's top-left.
- if (win.isDragResizeChanged()) {
+ if (win.isDragResizeChanged() || win.mResizedWhileNotDragResizing) {
win.setDragResizing();
+ win.mResizedWhileNotDragResizing = false;
// We can only change top level windows to the full-screen surface when
// resizing (as we only have one full-screen surface). So there is no need
// to preserve and destroy windows which are attached to another, they
@@ -3042,7 +3059,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
+ " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
- Animation a = mAppTransition.loadAnimation(lp, transit, enter,
+ Animation a = mAppTransition.loadAnimation(lp, transit, enter, mCurConfiguration.uiMode,
mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets,
isVoiceInteraction, freeform, atoken.mTask.mTaskId);
if (a != null) {
@@ -3611,6 +3628,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
private int[] onConfigurationChanged() {
+ mPolicy.onConfigurationChanged();
+ getDefaultDisplayContentLocked().getDockedDividerController().onConfigurationChanged();
mChangedStackList.clear();
for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
@@ -4135,6 +4154,14 @@ public class WindowManagerService extends IWindowManager.Stub
for (int i = 0; i < windowsCount; i++) {
WindowState win = wtoken.allAppWindows.get(i);
if (win == wtoken.startingWindow) {
+ // Starting window that's exiting will be removed when the animation
+ // finishes. Mark all relevant flags for that finishExit will proceed
+ // all the way to actually remove it.
+ if (!visible && win.isVisibleNow() && wtoken.mAppAnimator.isAnimating()) {
+ win.mAnimatingExit = true;
+ win.mRemoveOnExit = true;
+ win.mWindowRemovalAllowed = true;
+ }
continue;
}
@@ -4284,9 +4311,13 @@ public class WindowManagerService extends IWindowManager.Stub
wtoken.appDied = false;
wtoken.removeAllWindows();
} else if (visible) {
- mOpeningApps.add(wtoken);
+ if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
+ // Add the app mOpeningApps if transition is unset but ready. This means
+ // we're doing a screen freeze, and the unfreeze will wait for all opening
+ // apps to be ready.
+ mOpeningApps.add(wtoken);
+ }
wtoken.startingMoved = false;
-
// If the token is currently hidden (should be the common case), or has been
// stopped, then we need to set up to wait for its windows to be ready.
if (wtoken.hidden || wtoken.mAppStopped) {
@@ -4330,6 +4361,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
wtoken.inPendingTransaction = true;
if (visible) {
+ mOpeningApps.add(wtoken);
wtoken.mEnteringAnimation = true;
} else {
mClosingApps.add(wtoken);
@@ -6086,7 +6118,7 @@ public class WindowManagerService extends IWindowManager.Stub
int bottom = wf.bottom - cr.bottom;
frame.union(left, top, right, bottom);
ws.getVisibleBounds(stackBounds);
- if (!frame.intersect(stackBounds)) {
+ if (!Rect.intersects(frame, stackBounds)) {
// Set frame empty if there's no intersection.
frame.setEmpty();
}
@@ -7586,6 +7618,11 @@ public class WindowManagerService extends IWindowManager.Stub
+ " milliseconds before attempting to detect safe mode.");
}
+ if (Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
+ return false;
+ }
+
int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
KeyEvent.KEYCODE_MENU);
int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
@@ -8987,7 +9024,8 @@ public class WindowManagerService extends IWindowManager.Stub
|| winAnimator.mSurfaceResized
|| w.mOutsetsChanged
|| configChanged
- || dragResizingChanged) {
+ || dragResizingChanged
+ || w.mResizedWhileNotDragResizing) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
Slog.v(TAG_WM, "Resize reasons for w=" + w + ": "
+ " contentInsetsChanged=" + w.mContentInsetsChanged
@@ -9021,7 +9059,8 @@ public class WindowManagerService extends IWindowManager.Stub
// the display until this window has been redrawn; to do that,
// we need to go through the process of getting informed by the
// application when it has finished drawing.
- if (w.mOrientationChanging || dragResizingChanged) {
+ if (w.mOrientationChanging || dragResizingChanged
+ || w.mResizedWhileNotDragResizing) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
+ ", mDrawState=DRAW_PENDING in " + w
@@ -9381,6 +9420,10 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
+ if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
+ "startFreezingDisplayLocked: inTransaction=" + inTransaction
+ + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
+ + " called by " + Debug.getCallers(8));
mScreenFrozenLock.acquire();
mDisplayFrozen = true;
@@ -9451,6 +9494,9 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
+ if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
+ "stopFreezingDisplayLocked: Unfreezing now");
+
mDisplayFrozen = false;
mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
StringBuilder sb = new StringBuilder(128);
@@ -10615,7 +10661,10 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
try {
- getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
+ WindowState focusedWindow = getFocusedWindow();
+ if (focusedWindow != null && focusedWindow.mClient != null) {
+ getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
+ }
} catch (RemoteException e) {
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 57ead8b3a617..ddfc022aeb3f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -328,6 +328,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
final Rect mInsetFrame = new Rect();
+ private static final Rect sTmpRect = new Rect();
+
boolean mContentChanged;
// If a window showing a wallpaper: the requested offset for the
@@ -466,6 +468,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
boolean mResizedWhileGone = false;
+ /**
+ * Indicates whether we got resized but drag resizing flag was false. In this case, we also
+ * need to recreate the surface and defer surface bound updates in order to make sure the
+ * buffer contents and the positioning/size stay in sync.
+ */
+ boolean mResizedWhileNotDragResizing;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
@@ -629,6 +638,20 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mAttrs.packageName;
}
+ /**
+ * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
+ * from {@param frame}. In other words, it applies the insets that would result if
+ * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from
+ * {@param insetFrame}.
+ */
+ private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame) {
+ final int left = Math.max(0, insetFrame.left - layoutFrame.left);
+ final int top = Math.max(0, insetFrame.top - layoutFrame.top);
+ final int right = Math.max(0, layoutFrame.right - insetFrame.right);
+ final int bottom = Math.max(0, layoutFrame.bottom - insetFrame.bottom);
+ frame.inset(left, top, right, bottom);
+ }
+
@Override
public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf,
Rect osf) {
@@ -654,11 +677,25 @@ final class WindowState implements WindowManagerPolicy.WindowState {
task.getTempInsetBounds(mInsetFrame);
}
+ // Denotes the actual frame used to calculate the insets and to perform the layout. When
+ // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the
+ // insets temporarily. By the notion of a task having a different layout frame, we can
+ // achieve that while still moving the task around.
+ final Rect layoutContainingFrame;
+ final Rect layoutDisplayFrame;
+
+ // The offset from the layout containing frame to the actual containing frame.
+ final int layoutXDiff;
+ final int layoutYDiff;
if (mInsetFrame.isEmpty() && (fullscreenTask
|| layoutInParentFrame())) {
// We use the parent frame as the containing frame for fullscreen and child windows
mContainingFrame.set(pf);
mDisplayFrame.set(df);
+ layoutDisplayFrame = df;
+ layoutContainingFrame = pf;
+ layoutXDiff = 0;
+ layoutYDiff = 0;
} else {
task.getBounds(mContainingFrame);
if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
@@ -670,10 +707,18 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mContainingFrame.bottom = mContainingFrame.top + frozen.height();
}
final WindowState imeWin = mService.mInputMethodWindow;
- if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this
- && mContainingFrame.bottom > cf.bottom) {
- // IME is up and obscuring this window. Adjust the window position so it is visible.
- mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
+ // IME is up and obscuring this window. Adjust the window position so it is visible.
+ if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
+ if (windowsAreFloating && mContainingFrame.bottom > cf.bottom) {
+ // In freeform we want to move the top up directly.
+ // TODO: Investigate why this is cf not pf.
+ mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
+ } else if (mContainingFrame.bottom > pf.bottom) {
+ // But in docked we want to behave like fullscreen
+ // and behave as if the task were given smaller bounds
+ // for the purposes of layout.
+ mContainingFrame.bottom = pf.bottom;
+ }
}
if (windowsAreFloating) {
@@ -685,6 +730,14 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
mDisplayFrame.set(mContainingFrame);
+ layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0;
+ layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
+ layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
+ subtractInsets(mDisplayFrame, layoutContainingFrame, df);
+ subtractInsets(mContainingFrame, layoutContainingFrame, pf);
+ subtractInsets(mInsetFrame, layoutContainingFrame, pf);
+ layoutDisplayFrame = df;
+ layoutDisplayFrame.intersect(layoutContainingFrame);
}
final int pw = mContainingFrame.width();
@@ -715,7 +768,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
final int fw = mFrame.width();
final int fh = mFrame.height();
- applyGravityAndUpdateFrame();
+ applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
+
+ // Offset the actual frame by the amount layout frame is off.
+ mFrame.offset(-layoutXDiff, -layoutYDiff);
+ mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
// Calculate the outsets before the content frame gets shrinked to the window frame.
if (hasOutsets) {
@@ -727,12 +784,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mOutsets.set(0, 0, 0, 0);
}
- // Denotes the actual frame used to calculate the insets. When resizing in docked mode,
- // we'd like to freeze the layout, so we also need to freeze the insets temporarily. By the
- // notion of a task having a different inset frame, we can achieve that while still moving
- // the task around.
- final Rect frame = !mInsetFrame.isEmpty() ? mInsetFrame : mFrame;
-
// Make sure the content and visible frames are inside of the
// final window frame.
if (windowsAreFloating && !mFrame.isEmpty()) {
@@ -761,29 +812,29 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mMovedByResize = true;
}
} else {
- mContentFrame.set(Math.max(mContentFrame.left, frame.left),
- Math.max(mContentFrame.top, frame.top),
- Math.min(mContentFrame.right, frame.right),
- Math.min(mContentFrame.bottom, frame.bottom));
+ mContentFrame.set(Math.max(mContentFrame.left, layoutContainingFrame.left),
+ Math.max(mContentFrame.top, layoutContainingFrame.top),
+ Math.min(mContentFrame.right, layoutContainingFrame.right),
+ Math.min(mContentFrame.bottom, layoutContainingFrame.bottom));
- mVisibleFrame.set(Math.max(mVisibleFrame.left, frame.left),
- Math.max(mVisibleFrame.top, frame.top),
- Math.min(mVisibleFrame.right, frame.right),
- Math.min(mVisibleFrame.bottom, frame.bottom));
+ mVisibleFrame.set(Math.max(mVisibleFrame.left, layoutContainingFrame.left),
+ Math.max(mVisibleFrame.top, layoutContainingFrame.top),
+ Math.min(mVisibleFrame.right, layoutContainingFrame.right),
+ Math.min(mVisibleFrame.bottom, layoutContainingFrame.bottom));
- mStableFrame.set(Math.max(mStableFrame.left, frame.left),
- Math.max(mStableFrame.top, frame.top),
- Math.min(mStableFrame.right, frame.right),
- Math.min(mStableFrame.bottom, frame.bottom));
+ mStableFrame.set(Math.max(mStableFrame.left, layoutContainingFrame.left),
+ Math.max(mStableFrame.top, layoutContainingFrame.top),
+ Math.min(mStableFrame.right, layoutContainingFrame.right),
+ Math.min(mStableFrame.bottom, layoutContainingFrame.bottom));
}
if (fullscreenTask && !windowsAreFloating) {
// Windows that are not fullscreen can be positioned outside of the display frame,
// but that is not a reason to provide them with overscan insets.
- mOverscanInsets.set(Math.max(mOverscanFrame.left - frame.left, 0),
- Math.max(mOverscanFrame.top - frame.top, 0),
- Math.max(frame.right - mOverscanFrame.right, 0),
- Math.max(frame.bottom - mOverscanFrame.bottom, 0));
+ mOverscanInsets.set(Math.max(mOverscanFrame.left - layoutContainingFrame.left, 0),
+ Math.max(mOverscanFrame.top - layoutContainingFrame.top, 0),
+ Math.max(layoutContainingFrame.right - mOverscanFrame.right, 0),
+ Math.max(layoutContainingFrame.bottom - mOverscanFrame.bottom, 0));
}
if (mAttrs.type == TYPE_DOCK_DIVIDER) {
@@ -799,45 +850,37 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mContentInsets.setEmpty();
mVisibleInsets.setEmpty();
} else {
- // Using mContentInsets as a temp rect. It is safe because we're setting it below.
- getDisplayContent().getLogicalDisplayRect(mContentInsets);
+ getDisplayContent().getLogicalDisplayRect(mTmpRect);
// Override right and/or bottom insets in case if the frame doesn't fit the screen in
// non-fullscreen mode.
- boolean overrideRightInset = !fullscreenTask && mFrame.right > mContentInsets.right;
- boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mContentInsets.bottom;
- mContentInsets.set(mContentFrame.left - frame.left,
- mContentFrame.top - frame.top,
- overrideRightInset ? 0 : frame.right - mContentFrame.right,
- overrideBottomInset ? 0 : frame.bottom - mContentFrame.bottom);
-
- mVisibleInsets.set(mVisibleFrame.left - frame.left,
- mVisibleFrame.top - frame.top,
- overrideRightInset ? 0 : frame.right - mVisibleFrame.right,
- overrideBottomInset ? 0 : frame.bottom - mVisibleFrame.bottom);
+ boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right;
+ boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom;
+ mContentInsets.set(mContentFrame.left - layoutContainingFrame.left,
+ mContentFrame.top - layoutContainingFrame.top,
+ overrideRightInset ? mTmpRect.right - mContentFrame.right
+ : layoutContainingFrame.right - mContentFrame.right,
+ overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
+ : layoutContainingFrame.bottom - mContentFrame.bottom);
+
+ mVisibleInsets.set(mVisibleFrame.left - layoutContainingFrame.left,
+ mVisibleFrame.top - layoutContainingFrame.top,
+ overrideRightInset ? mTmpRect.right - mVisibleFrame.right
+ : layoutContainingFrame.right - mVisibleFrame.right,
+ overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
+ : layoutContainingFrame.bottom - mVisibleFrame.bottom);
+
+ mStableInsets.set(Math.max(mStableFrame.left - layoutContainingFrame.left, 0),
+ Math.max(mStableFrame.top - layoutContainingFrame.top, 0),
+ overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
+ : Math.max(layoutContainingFrame.right - mStableFrame.right, 0),
+ overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
+ : Math.max(layoutContainingFrame.bottom - mStableFrame.bottom, 0));
+ }
+
+ mContentFrame.offset(-layoutXDiff, -layoutYDiff);
+ mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
+ mStableFrame.offset(-layoutXDiff, -layoutYDiff);
- mStableInsets.set(Math.max(mStableFrame.left - frame.left, 0),
- Math.max(mStableFrame.top - frame.top, 0),
- overrideRightInset ? 0 : Math.max(frame.right - mStableFrame.right, 0),
- overrideBottomInset ? 0 : Math.max(frame.bottom - mStableFrame.bottom, 0));
- }
-
- if (!mInsetFrame.isEmpty()) {
- mContentFrame.set(mFrame);
- mContentFrame.top += mContentInsets.top;
- mContentFrame.bottom -= mContentInsets.bottom;
- mContentFrame.left += mContentInsets.left;
- mContentFrame.right -= mContentInsets.right;
- mVisibleFrame.set(mFrame);
- mVisibleFrame.top += mVisibleInsets.top;
- mVisibleFrame.bottom -= mVisibleInsets.bottom;
- mVisibleFrame.left += mVisibleInsets.left;
- mVisibleFrame.right -= mVisibleInsets.right;
- mStableFrame.set(mFrame);
- mStableFrame.top += mStableInsets.top;
- mStableFrame.bottom -= mStableInsets.bottom;
- mStableFrame.left += mStableInsets.left;
- mStableFrame.right -= mStableInsets.right;
- }
mCompatFrame.set(mFrame);
if (mEnforceSizeCompat) {
// If there is a size compatibility scale being applied to the
@@ -1878,6 +1921,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
private boolean shouldSaveSurface() {
+ if (mWinAnimator.mSurfaceController == null) {
+ // Don't bother if the surface controller is gone for any reason.
+ return false;
+ }
+
if ((mAttrs.flags & FLAG_SECURE) != 0) {
// We don't save secure surfaces since their content shouldn't be shown while the app
// isn't on screen and content might leak through during the transition animation with
@@ -1951,10 +1999,18 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return;
}
mSurfaceSaved = false;
- setHasSurface(true);
- mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
- if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
- Slog.v(TAG, "Restoring saved surface: " + this);
+ if (mWinAnimator.mSurfaceController != null) {
+ setHasSurface(true);
+ mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
+
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
+ Slog.v(TAG, "Restoring saved surface: " + this);
+ }
+ } else {
+ // mSurfaceController shouldn't be null if mSurfaceSaved was still true at
+ // this point. Even if we destroyed the saved surface because of rotation
+ // or resize, mSurfaceSaved flag should have been cleared. So this is a wtf.
+ Slog.wtf(TAG, "Failed to restore saved surface: surface gone! " + this);
}
}
@@ -2523,9 +2579,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
- void applyGravityAndUpdateFrame() {
- final int pw = mContainingFrame.width();
- final int ph = mContainingFrame.height();
+ void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
+ final int pw = containingFrame.width();
+ final int ph = containingFrame.height();
final Task task = getTask();
final boolean nonFullscreenTask = isInMultiWindowMode();
final boolean fitToDisplay = task != null && !task.isFloating() && !layoutInParentFrame();
@@ -2572,7 +2628,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
y = mAttrs.y;
}
- if (nonFullscreenTask) {
+ if (nonFullscreenTask && !layoutInParentFrame()) {
// Make sure window fits in containing frame since it is in a non-fullscreen task as
// required by {@link Gravity#apply} call.
w = Math.min(w, pw);
@@ -2580,13 +2636,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
// Set mFrame
- Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
+ Gravity.apply(mAttrs.gravity, w, h, containingFrame,
(int) (x + mAttrs.horizontalMargin * pw),
(int) (y + mAttrs.verticalMargin * ph), mFrame);
// Now make sure the window fits in the overall display frame.
if (fitToDisplay) {
- Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+ Gravity.applyDisplay(mAttrs.gravity, displayFrame, mFrame);
}
// We need to make sure we update the CompatFrame as it is used for
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1e103f0573e0..34452ee1eefa 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -967,13 +967,15 @@ class WindowStateAnimator {
if (appTransformation != null) {
tmpMatrix.postConcat(appTransformation.getMatrix());
}
- if (screenAnimation) {
- tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
- }
+
// The translation that applies the position of the window needs to be applied at the
// end in case that other translations include scaling. Otherwise the scaling will
- // affect this translation.
+ // affect this translation. But it needs to be set before the screen rotation animation
+ // so the pivot point is at the center of the screen for all windows.
tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
+ if (screenAnimation) {
+ tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
+ }
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
@@ -1316,6 +1318,11 @@ class WindowStateAnimator {
final WindowState w = mWin;
final Task task = w.getTask();
+ // We got resized, so block all updates until we got the new surface.
+ if (w.mResizedWhileNotDragResizing) {
+ return;
+ }
+
mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
calculateSurfaceBounds(w, w.getAttrs());
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index eda2f39480a8..04aa735bc99d 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1582,7 +1582,8 @@ class WindowSurfacePlacer {
// synchronize its thumbnail surface with the surface for the
// open/close animation (only on the way down)
anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
- insets, thumbnailHeader, taskId, mService.mCurConfiguration.orientation);
+ insets, thumbnailHeader, taskId, mService.mCurConfiguration.uiMode,
+ mService.mCurConfiguration.orientation);
openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
openingAppAnimator.deferThumbnailDestruction =
!mService.mAppTransition.isNextThumbnailTransitionScaleUp();
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index a5237ca89520..cd485c55c816 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1312,6 +1312,12 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
}
}
+static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */,
+ jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ im->getInputManager()->getReader()->toggleCapsLockState(deviceId);
+}
+
static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobjectArray windowHandleObjArray) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1508,6 +1514,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
(void*) nativeSetInputFilterEnabled },
{ "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
(void*) nativeInjectInputEvent },
+ { "nativeToggleCapsLock", "(JI)V",
+ (void*) nativeToggleCapsLock },
{ "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
(void*) nativeSetInputWindows },
{ "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6fe5c1680b1a..fdea84b4c2a4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1131,9 +1131,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
String tagDAM = parser.getName();
if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
- PersistableBundle bundle = new PersistableBundle();
- bundle.restoreFromXml(parser);
- result.options = bundle;
+ result.options = PersistableBundle.restoreFromXml(parser);
} else {
Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
}
@@ -2805,6 +2803,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
&& getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
throw new IllegalArgumentException("Admin is already added");
}
+ if (policy.mRemovingAdmins.contains(adminReceiver)) {
+ throw new IllegalArgumentException(
+ "Trying to set an admin which is being removed");
+ }
ActiveAdmin newAdmin = new ActiveAdmin(info, /* parent */ false);
policy.mAdminMap.put(adminReceiver, newAdmin);
int replaceIndex = -1;
@@ -3006,7 +3008,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ArrayList<ActiveAdmin> admins = new ArrayList<ActiveAdmin>();
for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
DevicePolicyData policy = getUserData(userInfo.id);
- if (!isManagedProfile(userInfo.id)) {
+ if (!userInfo.isManagedProfile()) {
admins.addAll(policy.mAdminList);
} else {
// For managed profiles, we always include the policies set on the parent
@@ -3740,32 +3742,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int callingUid = mInjector.binderGetCallingUid();
final int userHandle = mInjector.userHandleGetCallingUserId();
- if (getCredentialOwner(userHandle, /* parent */ false) != userHandle) {
- throw new SecurityException("You can not change password for this profile because"
- + " it shares the password with the owner profile");
- }
-
String password = passwordOrNull != null ? passwordOrNull : "";
+ // Password resetting to empty/null is not allowed for managed profiles.
+ if (TextUtils.isEmpty(password)) {
+ enforceNotManagedProfile(userHandle, "clear the active password");
+ }
+
int quality;
synchronized (this) {
- // If caller has PO (or DO), it can clear the password, so see if that's the case
- // first.
+ // If caller has PO (or DO) it can change the password, so see if that's the case first.
ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
if (admin == null) {
// Otherwise, make sure the caller has any active admin with the right policy.
admin = getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
- }
- final ComponentName adminComponent = admin.info.getComponent();
-
- // As of N, only profile owners and device owners can reset the password.
- if (!(isProfileOwner(adminComponent, userHandle)
- || isDeviceOwner(adminComponent, userHandle))) {
final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle)
<= android.os.Build.VERSION_CODES.M;
+
// As of N, password resetting to empty/null is not allowed anymore.
// TODO Should we allow DO/PO to set an empty password?
if (TextUtils.isEmpty(password)) {
@@ -3982,6 +3978,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
&& timeMs > admin.maximumTimeToUnlock) {
timeMs = admin.maximumTimeToUnlock;
}
+ // If userInfo.id is a managed profile, we also need to look at
+ // the policies set on the parent.
+ if (admin.hasParentActiveAdmin()) {
+ final ActiveAdmin parentAdmin = admin.getParentActiveAdmin();
+ if (parentAdmin.maximumTimeToUnlock > 0
+ && timeMs > parentAdmin.maximumTimeToUnlock) {
+ timeMs = parentAdmin.maximumTimeToUnlock;
+ }
+ }
}
}
@@ -4015,30 +4020,57 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
- long time = 0;
-
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
- return admin != null ? admin.maximumTimeToUnlock : time;
+ return admin != null ? admin.maximumTimeToUnlock : 0;
}
-
// Return the strictest policy across all participating admins.
List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(
userHandle, parent);
- final int N = admins.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = admins.get(i);
- if (time == 0) {
- time = admin.maximumTimeToUnlock;
- } else if (admin.maximumTimeToUnlock != 0
- && time > admin.maximumTimeToUnlock) {
- time = admin.maximumTimeToUnlock;
+ return getMaximumTimeToLockPolicyFromAdmins(admins);
+ }
+ }
+
+ @Override
+ public long getMaximumTimeToLockForUserAndProfiles(int userHandle) {
+ if (!mHasFeature) {
+ return 0;
+ }
+ enforceFullCrossUsersPermission(userHandle);
+ synchronized (this) {
+ // All admins for this user.
+ ArrayList<ActiveAdmin> admins = new ArrayList<ActiveAdmin>();
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ DevicePolicyData policy = getUserData(userInfo.id);
+ admins.addAll(policy.mAdminList);
+ // If it is a managed profile, it may have parent active admins
+ if (userInfo.isManagedProfile()) {
+ for (ActiveAdmin admin : policy.mAdminList) {
+ if (admin.hasParentActiveAdmin()) {
+ admins.add(admin.getParentActiveAdmin());
+ }
+ }
}
}
- return time;
+ return getMaximumTimeToLockPolicyFromAdmins(admins);
}
}
+ private long getMaximumTimeToLockPolicyFromAdmins(List<ActiveAdmin> admins) {
+ long time = 0;
+ final int N = admins.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = admins.get(i);
+ if (time == 0) {
+ time = admin.maximumTimeToUnlock;
+ } else if (admin.maximumTimeToUnlock != 0
+ && time > admin.maximumTimeToUnlock) {
+ time = admin.maximumTimeToUnlock;
+ }
+ }
+ return time;
+ }
+
@Override
public void lockNow(boolean parent) {
if (!mHasFeature) {
@@ -4356,6 +4388,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ /**
+ * @return {@code true} if the package is installed and set as always-on, {@code false} if it is
+ * not installed and therefore not available.
+ *
+ * @throws SecurityException if the caller is not a profile or device owner.
+ * @throws UnsupportedException if the package does not support being set as always-on.
+ */
@Override
public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage)
throws SecurityException {
@@ -4365,13 +4404,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int userId = mInjector.userHandleGetCallingUserId();
final long token = mInjector.binderClearCallingIdentity();
- try{
+ try {
+ if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
+ return false;
+ }
ConnectivityManager connectivityManager = (ConnectivityManager)
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- return connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage);
+ if (!connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage)) {
+ throw new UnsupportedOperationException();
+ }
} finally {
mInjector.binderRestoreCallingIdentity(token);
}
+ return true;
}
@Override
@@ -6394,17 +6439,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent,
- PersistableBundle args) {
+ PersistableBundle args, boolean parent) {
if (!mHasFeature) {
return;
}
Preconditions.checkNotNull(admin, "admin is null");
Preconditions.checkNotNull(agent, "agent is null");
final int userHandle = UserHandle.getCallingUserId();
- enforceNotManagedProfile(userHandle, "set trust agent configuration");
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
+ DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent);
ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
saveSettingsLocked(userHandle);
}
@@ -6412,7 +6456,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
- ComponentName agent, int userHandle) {
+ ComponentName agent, int userHandle, boolean parent) {
if (!mHasFeature) {
return null;
}
@@ -6422,46 +6466,44 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
final String componentName = agent.flattenToString();
if (admin != null) {
- final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle);
+ final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle, parent);
if (ap == null) return null;
TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName);
if (trustAgentInfo == null || trustAgentInfo.options == null) return null;
- List<PersistableBundle> result = new ArrayList<PersistableBundle>();
+ List<PersistableBundle> result = new ArrayList<>();
result.add(trustAgentInfo.options);
return result;
}
// Return strictest policy for this user and profiles that are visible from this user.
- final List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
List<PersistableBundle> result = null;
-
// Search through all admins that use KEYGUARD_DISABLE_TRUST_AGENTS and keep track
// of the options. If any admin doesn't have options, discard options for the rest
// and return null.
+ List<ActiveAdmin> admins =
+ getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent);
boolean allAdminsHaveOptions = true;
- for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
- final int N = policy.mAdminList.size();
- for (int i=0; i < N; i++) {
- final ActiveAdmin active = policy.mAdminList.get(i);
- final boolean disablesTrust = (active.disabledKeyguardFeatures
- & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
- final TrustAgentInfo info = active.trustAgentInfos.get(componentName);
- if (info != null && info.options != null && !info.options.isEmpty()) {
- if (disablesTrust) {
- if (result == null) {
- result = new ArrayList<PersistableBundle>();
- }
- result.add(info.options);
- } else {
- Log.w(LOG_TAG, "Ignoring admin " + active.info
- + " because it has trust options but doesn't declare "
- + "KEYGUARD_DISABLE_TRUST_AGENTS");
+ final int N = admins.size();
+ for (int i = 0; i < N; i++) {
+ final ActiveAdmin active = admins.get(i);
+
+ final boolean disablesTrust = (active.disabledKeyguardFeatures
+ & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
+ final TrustAgentInfo info = active.trustAgentInfos.get(componentName);
+ if (info != null && info.options != null && !info.options.isEmpty()) {
+ if (disablesTrust) {
+ if (result == null) {
+ result = new ArrayList<>();
}
- } else if (disablesTrust) {
- allAdminsHaveOptions = false;
- break;
+ result.add(info.options);
+ } else {
+ Log.w(LOG_TAG, "Ignoring admin " + active.info
+ + " because it has trust options but doesn't declare "
+ + "KEYGUARD_DISABLE_TRUST_AGENTS");
}
+ } else if (disablesTrust) {
+ allAdminsHaveOptions = false;
+ break;
}
}
return allAdminsHaveOptions ? result : null;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 659450efcce3..e7ae2b0fcfd5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -157,6 +157,8 @@ public final class SystemServer {
"com.google.android.clockwork.ThermalObserver";
private static final String WEAR_BLUETOOTH_SERVICE_CLASS =
"com.google.android.clockwork.bluetooth.WearBluetoothService";
+ private static final String CONTENT_SERVICE_CLASS =
+ "com.android.server.content.ContentService$Lifecycle";
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
@@ -574,8 +576,7 @@ public final class SystemServer {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
traceBeginAndSlog("StartContentService");
- contentService = ContentService.main(context,
- mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);
+ mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
traceBeginAndSlog("InstallSystemProviders");
@@ -1324,7 +1325,7 @@ public final class SystemServer {
reportWtf("starting System UI", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeMountServiceReady");
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkScoreReady");
try {
if (networkScoreF != null) networkScoreF.systemReady();
} catch (Throwable e) {
@@ -1423,6 +1424,12 @@ public final class SystemServer {
} catch (Throwable e) {
reportWtf("Notifying MmsService running", e);
}
+
+ try {
+ if (networkScoreF != null) networkScoreF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying NetworkScoreService running", e);
+ }
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
});
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index ebbf99101e42..f430a3034630 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -18,6 +18,7 @@ package android.net.apf;
import static android.system.OsConstants.*;
+import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.apf.ApfGenerator;
import android.net.apf.ApfGenerator.IllegalInstructionException;
@@ -136,6 +137,16 @@ public class ApfFilter {
// NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28;
+ private static int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
+ private static final byte[] ARP_IPV4_REQUEST_HEADER = new byte[]{
+ 0, 1, // Hardware type: Ethernet (1)
+ 8, 0, // Protocol type: IP (0x0800)
+ 6, // Hardware size: 6
+ 4, // Protocol size: 4
+ 0, 1 // Opcode: request (1)
+ };
+ private static int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
+
private final ApfCapabilities mApfCapabilities;
private final IpManager.Callback mIpManagerCallback;
private final NetworkInterface mNetworkInterface;
@@ -145,12 +156,16 @@ public class ApfFilter {
private long mUniqueCounter;
@GuardedBy("this")
private boolean mMulticastFilter;
+ // Our IPv4 address, if we have just one, otherwise null.
+ @GuardedBy("this")
+ private byte[] mIPv4Address;
private ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface,
- IpManager.Callback ipManagerCallback) {
+ IpManager.Callback ipManagerCallback, boolean multicastFilter) {
mApfCapabilities = apfCapabilities;
mIpManagerCallback = ipManagerCallback;
mNetworkInterface = networkInterface;
+ mMulticastFilter = multicastFilter;
maybeStartFilter();
}
@@ -225,6 +240,7 @@ public class ApfFilter {
private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
+ // Note: mPacket's position() cannot be assumed to be reset.
private final ByteBuffer mPacket;
// List of binary ranges that include the whole packet except the lifetimes.
// Pairs consist of offset and length.
@@ -378,17 +394,12 @@ public class ApfFilter {
// Ignoring lifetimes (which may change) does {@code packet} match this RA?
boolean matches(byte[] packet, int length) {
- if (length != mPacket.limit()) return false;
- ByteBuffer a = ByteBuffer.wrap(packet);
- ByteBuffer b = mPacket;
+ if (length != mPacket.capacity()) return false;
+ byte[] referencePacket = mPacket.array();
for (Pair<Integer, Integer> nonLifetime : mNonLifetimes) {
- a.clear();
- b.clear();
- a.position(nonLifetime.first);
- b.position(nonLifetime.first);
- a.limit(nonLifetime.first + nonLifetime.second);
- b.limit(nonLifetime.first + nonLifetime.second);
- if (a.compareTo(b) != 0) return false;
+ for (int i = nonLifetime.first; i < (nonLifetime.first + nonLifetime.second); i++) {
+ if (packet[i] != referencePacket[i]) return false;
+ }
}
return true;
}
@@ -440,7 +451,7 @@ public class ApfFilter {
String nextFilterLabel = "Ra" + getUniqueNumberLocked();
// Skip if packet is not the right size
gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
- gen.addJumpIfR0NotEquals(mPacket.limit(), nextFilterLabel);
+ gen.addJumpIfR0NotEquals(mPacket.capacity(), nextFilterLabel);
int filterLifetime = (int)(currentLifetime() / FRACTION_OF_LIFETIME_TO_FILTER);
// Skip filter if expired
gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
@@ -510,6 +521,33 @@ public class ApfFilter {
private byte[] mLastInstalledProgram;
/**
+ * Generate filter code to process ARP packets. Execution of this code ends in either the
+ * DROP_LABEL or PASS_LABEL and does not fall off the end.
+ * Preconditions:
+ * - Packet being filtered is ARP
+ */
+ @GuardedBy("this")
+ private void generateArpFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
+ // Here's a basic summary of what the ARP filter program does:
+ //
+ // if it's not an ARP IPv4 request:
+ // pass
+ // if it's not a request for our IPv4 address:
+ // drop
+ // pass
+
+ // if it's not an ARP IPv4 request, pass
+ gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_REQUEST_HEADER, gen.PASS_LABEL);
+ // if it's not a request for our IPv4 address, drop
+ gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, gen.DROP_LABEL);
+
+ // Otherwise, pass
+ gen.addJump(gen.PASS_LABEL);
+ }
+
+ /**
* Generate filter code to process IPv4 packets. Execution of this code ends in either the
* DROP_LABEL or PASS_LABEL and does not fall off the end.
* Preconditions:
@@ -566,7 +604,6 @@ public class ApfFilter {
* DROP_LABEL or PASS_LABEL, or falls off the end for ICMPv6 packets.
* Preconditions:
* - Packet being filtered is IPv6
- * - R1 is initialized to 0
*/
@GuardedBy("this")
private void generateIPv6FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
@@ -598,6 +635,7 @@ public class ApfFilter {
/**
* Begin generating an APF program to:
* <ul>
+ * <li>Drop ARP requests not for us, if mIPv4Address is set,
* <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
* <li>Drop IPv4 multicast packets, if mMulticastFilter,
* <li>Pass all other IPv4 packets,
@@ -616,16 +654,31 @@ public class ApfFilter {
// Here's a basic summary of what the initial program does:
//
+ // if it's ARP:
+ // inesrt ARP filter to drop or pass these appropriately
// if it's IPv4:
// insert IPv4 filter to drop or pass these appropriately
// if it's not IPv6:
// pass
// insert IPv6 filter to drop, pass, or fall off the end for ICMPv6 packets
+ gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
+
+ if (mIPv4Address != null) {
+ // Add ARP filters:
+ String skipArpFiltersLabel = "skipArpFilters";
+ // If not ARP, skip ARP filters
+ // NOTE: Relies on R0 containing ethertype.
+ gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
+ generateArpFilterLocked(gen);
+ gen.defineLabel(skipArpFiltersLabel);
+ }
+
// Add IPv4 filters:
String skipIPv4FiltersLabel = "skipIPv4Filters";
- // If not IPv4, skip IPv4 filters
- gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
+ // NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
+ // execute the ARP filter, since that filter does not fall through, but either drops or
+ // passes.
gen.addJumpIfR0NotEquals(ETH_P_IP, skipIPv4FiltersLabel);
// NOTE: Relies on R1 being initialized to 0.
generateIPv4FilterLocked(gen);
@@ -634,8 +687,8 @@ public class ApfFilter {
// Add IPv6 filters:
// If not IPv6, pass
// NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
- // execute the IPv4 filter, since that filter does not fall through, but either drops or
- // passes.
+ // execute the ARP or IPv4 filters, since those filters do not fall through, but either
+ // drop or pass.
gen.addJumpIfR0NotEquals(ETH_P_IPV6, gen.PASS_LABEL);
generateIPv6FilterLocked(gen);
return gen;
@@ -752,7 +805,8 @@ public class ApfFilter {
* filtering using APF programs.
*/
public static ApfFilter maybeCreate(ApfCapabilities apfCapabilities,
- NetworkInterface networkInterface, IpManager.Callback ipManagerCallback) {
+ NetworkInterface networkInterface, IpManager.Callback ipManagerCallback,
+ boolean multicastFilter) {
if (apfCapabilities == null || networkInterface == null) return null;
if (apfCapabilities.apfVersionSupported == 0) return null;
if (apfCapabilities.maximumApfProgramSize < 512) {
@@ -768,7 +822,7 @@ public class ApfFilter {
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
return null;
}
- return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback);
+ return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback, multicastFilter);
}
public synchronized void shutdown() {
@@ -787,10 +841,36 @@ public class ApfFilter {
}
}
+ // Find the single IPv4 address if there is one, otherwise return null.
+ private static byte[] findIPv4Address(LinkProperties lp) {
+ byte[] ipv4Address = null;
+ for (InetAddress inetAddr : lp.getAddresses()) {
+ byte[] addr = inetAddr.getAddress();
+ if (addr.length != 4) continue;
+ // More than one IPv4 address, abort
+ if (ipv4Address != null && !Arrays.equals(ipv4Address, addr)) return null;
+ ipv4Address = addr;
+ }
+ return ipv4Address;
+ }
+
+ public synchronized void setLinkProperties(LinkProperties lp) {
+ // NOTE: Do not keep a copy of LinkProperties as it would further duplicate state.
+ byte[] ipv4Address = findIPv4Address(lp);
+ // If ipv4Address is the same as mIPv4Address, then there's no change, just return.
+ if (Arrays.equals(ipv4Address, mIPv4Address)) return;
+ // Otherwise update mIPv4Address and install new program.
+ mIPv4Address = ipv4Address;
+ installNewProgramLocked();
+ }
+
public synchronized void dump(IndentingPrintWriter pw) {
- pw.println("APF version: " + mApfCapabilities.apfVersionSupported);
- pw.println("Max program size: " + mApfCapabilities.maximumApfProgramSize);
+ pw.println("APF caps: " + mApfCapabilities);
pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
+ pw.println("Multicast filtering: " + mMulticastFilter);
+ try {
+ pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address));
+ } catch (UnknownHostException|NullPointerException e) {}
if (mLastTimeInstalledProgram == 0) {
pw.println("No program installed.");
return;
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index d10834ad9695..54aeb3db7319 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -100,10 +100,6 @@ public class IpManager extends StateMachine {
public void onProvisioningSuccess(LinkProperties newLp) {}
public void onProvisioningFailure(LinkProperties newLp) {}
- // This is called whenever 464xlat is being enabled or disabled (i.e.
- // started or stopped).
- public void on464XlatChange(boolean enabled) {}
-
// Invoked on LinkProperties changes.
public void onLinkPropertiesChange(LinkProperties newLp) {}
@@ -116,6 +112,14 @@ public class IpManager extends StateMachine {
// Install an APF program to filter incoming packets.
public void installPacketFilter(byte[] filter) {}
+
+ // If multicast filtering cannot be accomplished with APF, this function will be called to
+ // actuate multicast filtering using another means.
+ public void setFallbackMulticastFilter(boolean enabled) {}
+
+ // Enabled/disable Neighbor Discover offload functionality. This is
+ // called, for example, whenever 464xlat is being started or stopped.
+ public void setNeighborDiscoveryOffload(boolean enable) {}
}
public static class WaitForProvisioningCallback extends Callback {
@@ -222,6 +226,7 @@ public class IpManager extends StateMachine {
private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 5;
private static final int CMD_UPDATE_TCP_BUFFER_SIZES = 6;
private static final int CMD_UPDATE_HTTP_PROXY = 7;
+ private static final int CMD_SET_MULTICAST_FILTER = 8;
private static final int MAX_LOG_RECORDS = 1000;
@@ -258,6 +263,7 @@ public class IpManager extends StateMachine {
private String mTcpBufferSizes;
private ProxyInfo mHttpProxy;
private ApfFilter mApfFilter;
+ private boolean mMulticastFiltering;
/**
* Member variables accessed both from within the StateMachine thread
@@ -296,15 +302,20 @@ public class IpManager extends StateMachine {
}) {
@Override
public void interfaceAdded(String iface) {
+ super.interfaceAdded(iface);
if (mClatInterfaceName.equals(iface)) {
- mCallback.on464XlatChange(true);
+ mCallback.setNeighborDiscoveryOffload(false);
}
}
@Override
public void interfaceRemoved(String iface) {
+ super.interfaceRemoved(iface);
if (mClatInterfaceName.equals(iface)) {
- mCallback.on464XlatChange(false);
+ // TODO: consider sending a message to the IpManager main
+ // StateMachine thread, in case "NDO enabled" state becomes
+ // tied to more things that 464xlat operation.
+ mCallback.setNeighborDiscoveryOffload(true);
}
}
};
@@ -390,6 +401,14 @@ public class IpManager extends StateMachine {
sendMessage(CMD_UPDATE_HTTP_PROXY, proxyInfo);
}
+ /**
+ * Enable or disable the multicast filter. Attempts to use APF to accomplish the filtering,
+ * if not, Callback.setFallbackMulticastFilter() is called.
+ */
+ public void setMulticastFilter(boolean enabled) {
+ sendMessage(CMD_SET_MULTICAST_FILTER, enabled);
+ }
+
public LinkProperties getLinkProperties() {
synchronized (mLock) {
return new LinkProperties(mLinkProperties);
@@ -519,6 +538,7 @@ public class IpManager extends StateMachine {
}
private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) {
+ if (mApfFilter != null) mApfFilter.setLinkProperties(newLp);
switch (delta) {
case GAINED_PROVISIONING:
if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); }
@@ -729,6 +749,10 @@ public class IpManager extends StateMachine {
handleLinkPropertiesUpdate(NO_CALLBACKS);
break;
+ case CMD_SET_MULTICAST_FILTER:
+ mMulticastFiltering = (boolean) msg.obj;
+ break;
+
case DhcpClient.CMD_ON_QUIT:
// Everything is already stopped.
Log.e(mTag, "Unexpected CMD_ON_QUIT (already stopped).");
@@ -769,7 +793,10 @@ public class IpManager extends StateMachine {
@Override
public void enter() {
mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
- mCallback);
+ mCallback, mMulticastFiltering);
+ // TODO: investigate the effects of any multicast filtering racing/interfering with the
+ // rest of this IP configuration startup.
+ if (mApfFilter == null) mCallback.setFallbackMulticastFilter(mMulticastFiltering);
// Set privacy extensions.
try {
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
@@ -882,6 +909,16 @@ public class IpManager extends StateMachine {
handleLinkPropertiesUpdate(SEND_CALLBACKS);
break;
+ case CMD_SET_MULTICAST_FILTER: {
+ mMulticastFiltering = (boolean) msg.obj;
+ if (mApfFilter != null) {
+ mApfFilter.setMulticastFilter(mMulticastFiltering);
+ } else {
+ mCallback.setFallbackMulticastFilter(mMulticastFiltering);
+ }
+ break;
+ }
+
case DhcpClient.CMD_PRE_DHCP_ACTION:
if (VDBG) { Log.d(mTag, "onPreDhcpAction()"); }
if (mConfiguration.mRequestedPreDhcpAction) {
diff --git a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
index 5b70c17ae28d..07280bc881d8 100644
--- a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
@@ -62,7 +62,7 @@ public class ObserverNodeTest extends AndroidTestCase {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
for (int i = nums.length - 1; i >=0; --i) {
- root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
+ root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}
@@ -92,7 +92,7 @@ public class ObserverNodeTest extends AndroidTestCase {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
for (int i = uris.length - 1; i >=0; --i) {
- root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
+ root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index 0e2a80c8b302..baa5d361c1a1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -16,8 +16,11 @@
package com.android.server.pm;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -46,6 +49,7 @@ import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.Signature;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
@@ -68,6 +72,7 @@ import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.frameworks.servicestests.R;
@@ -99,6 +104,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.BiPredicate;
import java.util.function.Consumer;
/**
@@ -124,7 +130,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
*/
private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH true
- private static final boolean DUMP_ON_TEARDOWN = false; // DO NOT SUBMIT WITH true
+ private static final boolean DUMP_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true
// public for mockito
public class BaseContext extends MockContext {
@@ -264,9 +270,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
@Override
boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
- // Sort of hack; do a simpler check.
- return LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage)
- || LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage);
+ return mDefaultLauncherChecker.test(callingPackage, userId);
}
@Override
@@ -284,12 +288,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
@Override
void postToHandler(Runnable r) {
final long token = mContext.injectClearCallingIdentity();
- super.postToHandler(r);
- try {
- runTestOnUiThread(() -> {});
- } catch (Throwable e) {
- fail("runTestOnUiThread failed: " + e);
- }
+ r.run();
mContext.injectRestoreCallingIdentity(token);
}
@@ -321,36 +320,11 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
}
@Override
- public void ensureInUserProfiles(UserHandle userToCheck, String message) {
- if (getCallingUserId() == userToCheck.getIdentifier()) {
- return; // okay
- }
- if (getCallingUserId() == USER_0 && userToCheck.getIdentifier() == USER_P0) {
- return; // profile, okay.
- }
- if (getCallingUserId() == USER_P0 && userToCheck.getIdentifier() == USER_0) {
- return; // profile, okay.
- }
-
- if (mInjectedCallingUid != Process.SYSTEM_UID) {
- throw new SecurityException("To access other users, you need to be SYSTEM" +
- ", but current UID=" + mInjectedCallingUid);
- }
- }
-
- @Override
public void verifyCallingPackage(String callingPackage) {
// SKIP
}
@Override
- boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, String debugMsg) {
- // This requires CROSS_USER
- assertEquals(Process.SYSTEM_UID, mInjectedCallingUid);
- return user.getIdentifier() == listeningUser.getIdentifier();
- }
-
- @Override
void postToPackageMonitorHandler(Runnable r) {
final long token = mContext.injectClearCallingIdentity();
r.run();
@@ -361,6 +335,18 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
int injectBinderCallingUid() {
return mInjectedCallingUid;
}
+
+ @Override
+ long injectClearCallingIdentity() {
+ final int prevCallingUid = mInjectedCallingUid;
+ mInjectedCallingUid = Process.SYSTEM_UID;
+ return prevCallingUid;
+ }
+
+ @Override
+ void injectRestoreCallingIdentity(long token) {
+ mInjectedCallingUid = (int) token;
+ }
}
private class LauncherAppsTestable extends LauncherApps {
@@ -386,7 +372,11 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
private ShortcutServiceInternal mInternal;
private LauncherAppImplTestable mLauncherAppImpl;
- private LauncherAppsTestable mLauncherApps;
+
+ // LauncherApps has per-instace state, so we need a differnt instance for each launcher.
+ private final Map<Pair<Integer, String>, LauncherAppsTestable>
+ mLauncherAppsMap = new HashMap<>();
+ private LauncherAppsTestable mLauncherApps; // Current one
private File mInjectedFilePathRoot;
@@ -439,6 +429,24 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
private static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11);
private static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0);
+ private static final UserInfo USER_INFO_0 = withProfileGroupId(
+ new UserInfo(USER_0, "user0",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED), 10);
+
+ private static final UserInfo USER_INFO_10 =
+ new UserInfo(USER_10, "user10", UserInfo.FLAG_INITIALIZED);
+
+ private static final UserInfo USER_INFO_11 =
+ new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED);
+
+ private static final UserInfo USER_INFO_P0 = withProfileGroupId(
+ new UserInfo(USER_P0, "userP0",
+ UserInfo.FLAG_MANAGED_PROFILE), 10);
+
+ private BiPredicate<String, Integer> mDefaultLauncherChecker =
+ (callingPackage, userId) ->
+ LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage)
+ || LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage);
private static final long START_TIME = 1440000000101L;
@@ -494,20 +502,46 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files");
- // Empty the data directory.
- if (mInjectedFilePathRoot.exists()) {
- Assert.assertTrue("failed to delete dir",
- FileUtils.deleteContents(mInjectedFilePathRoot));
- }
- mInjectedFilePathRoot.mkdirs();
+ deleteAllSavedFiles();
+
+ // Set up users.
+ doAnswer(inv -> {
+ assertSystem();
+ return USER_INFO_0;
+ }).when(mMockUserManager).getUserInfo(eq(USER_0));
+
+ doAnswer(inv -> {
+ assertSystem();
+ return USER_INFO_10;
+ }).when(mMockUserManager).getUserInfo(eq(USER_10));
+
+ doAnswer(inv -> {
+ assertSystem();
+ return USER_INFO_11;
+ }).when(mMockUserManager).getUserInfo(eq(USER_11));
+
+ doAnswer(inv -> {
+ assertSystem();
+ return USER_INFO_P0;
+ }).when(mMockUserManager).getUserInfo(eq(USER_P0));
+
+ // User 0 is always running.
+ when(mMockUserManager.isUserRunning(eq(USER_0))).thenReturn(true);
initService();
setCaller(CALLING_PACKAGE_1);
}
+ private static UserInfo withProfileGroupId(UserInfo in, int groupId) {
+ in.profileGroupId = groupId;
+ return in;
+ }
+
@Override
protected void tearDown() throws Exception {
- if (DUMP_ON_TEARDOWN) dumpsysOnLogcat("Teardown");
+ if (DUMP_IN_TEARDOWN) dumpsysOnLogcat("Teardown");
+
+ shutdownServices();
super.tearDown();
}
@@ -516,8 +550,19 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
return getInstrumentation().getContext();
}
+ private void deleteAllSavedFiles() {
+ // Empty the data directory.
+ if (mInjectedFilePathRoot.exists()) {
+ Assert.assertTrue("failed to delete dir",
+ FileUtils.deleteContents(mInjectedFilePathRoot));
+ }
+ mInjectedFilePathRoot.mkdirs();
+ }
+
/** (Re-) init the manager and the service. */
private void initService() {
+ shutdownServices();
+
LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
// Instantiate targets.
@@ -527,12 +572,28 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
mInternal = LocalServices.getService(ShortcutServiceInternal.class);
mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext);
- mLauncherApps = new LauncherAppsTestable(mClientContext, mLauncherAppImpl);
+ mLauncherApps = null;
+ mLauncherAppsMap.clear();
// Load the setting file.
mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
}
+ private void shutdownServices() {
+ if (mService != null) {
+ // Flush all the unsaved data from the previous instance.
+ mService.saveDirtyInfo();
+ }
+ LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+
+ mService = null;
+ mManager = null;
+ mInternal = null;
+ mLauncherAppImpl = null;
+ mLauncherApps = null;
+ mLauncherAppsMap.clear();
+ }
+
private void addPackage(String packageName, int uid, int version) {
addPackage(packageName, uid, version, packageName);
}
@@ -615,6 +676,13 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
mInjectedCallingUid =
Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false),
"Unknown package").applicationInfo.uid;
+
+ // Set up LauncherApps for this caller.
+ final Pair<Integer, String> key = Pair.create(userId, packageName);
+ if (!mLauncherAppsMap.containsKey(key)) {
+ mLauncherAppsMap.put(key, new LauncherAppsTestable(mClientContext, mLauncherAppImpl));
+ }
+ mLauncherApps = mLauncherAppsMap.get(key);
}
private void setCaller(String packageName) {
@@ -625,6 +693,10 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
return mInjectedClientPackage;
}
+ private void setDefaultLauncherChecker(BiPredicate<String, Integer> p) {
+ mDefaultLauncherChecker = p;
+ }
+
private void runWithCaller(String packageName, int userId, Runnable r) {
final String previousPackage = mInjectedClientPackage;
final int previousUserId = UserHandle.getUserId(mInjectedCallingUid);
@@ -849,6 +921,12 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
return ret;
}
+ private static void resetAll(Collection<?> mocks) {
+ for (Object o : mocks) {
+ reset(o);
+ }
+ }
+
@NonNull
private ShortcutInfo findById(List<ShortcutInfo> list, String id) {
for (ShortcutInfo s : list) {
@@ -860,6 +938,10 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
return null;
}
+ private void assertSystem() {
+ assertEquals("Caller must be system", Process.SYSTEM_UID, mInjectedCallingUid);
+ }
+
private void assertResetTimes(long expectedLastResetTime, long expectedNextResetTime) {
assertEquals(expectedLastResetTime, mService.getLastResetTimeLocked());
assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
@@ -948,7 +1030,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
private List<ShortcutInfo> assertAllHaveIcon(
@NonNull List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.hasIconFile() || s.hasIconResource());
+ assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
}
return actualShortcuts;
}
@@ -957,7 +1039,8 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
int shortcutFlags) {
for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.hasFlags(shortcutFlags));
+ assertTrue("ID " + s.getId() + " doesn't have flags " + shortcutFlags,
+ s.hasFlags(shortcutFlags));
}
return actualShortcuts;
}
@@ -3008,12 +3091,6 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
}
public void testLauncherCallback() throws Throwable {
-
- // TODO Add "multi" version -- run the test with two launchers and make sure the callback
- // argument only contains the ones that are actually visible to each launcher.
-
- when(mMockUserManager.isUserRunning(eq(USER_0))).thenReturn(true);
-
LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
// Set listeners
@@ -3069,6 +3146,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
// Test for addDynamicShortcut.
reset(c0);
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+ dumpsysOnLogcat("before addDynamicShortcut");
assertTrue(mManager.addDynamicShortcut(makeShortcut("s4")));
});
@@ -3146,6 +3224,156 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertEquals(0, shortcuts.getValue().size());
}
+ private void assertCallbackNotReceived(LauncherApps.Callback mock) {
+ verify(mock, times(0)).onShortcutsChanged(anyString(), anyList(),
+ any(UserHandle.class));
+ }
+
+ private void assertCallbackReceived(LauncherApps.Callback mock,
+ UserHandle user, String packageName, String... ids) {
+ ArgumentCaptor<List> shortcutsCaptor = ArgumentCaptor.forClass(List.class);
+
+ verify(mock, times(1)).onShortcutsChanged(eq(packageName), shortcutsCaptor.capture(),
+ eq(user));
+ assertShortcutIds(shortcutsCaptor.getValue(), ids);
+ }
+
+ public void testLauncherCallback_crossProfile() throws Throwable {
+ prepareCrossProfileDataSet();
+
+ final Handler h = new Handler(Looper.getMainLooper());
+
+ final LauncherApps.Callback c0_1 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c0_2 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c0_3 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c0_4 = mock(LauncherApps.Callback.class);
+
+ final LauncherApps.Callback cP0_1 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c10_1 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c10_2 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c11_1 = mock(LauncherApps.Callback.class);
+
+ final List<LauncherApps.Callback> all =
+ list(c0_1, c0_2, c0_3, c0_4, cP0_1, c10_1, c11_1);
+
+ setDefaultLauncherChecker((pkg, userId) -> {
+ switch (userId) {
+ case USER_0:
+ return LAUNCHER_2.equals(pkg);
+ case USER_P0:
+ return LAUNCHER_1.equals(pkg);
+ case USER_10:
+ return LAUNCHER_1.equals(pkg);
+ case USER_11:
+ return LAUNCHER_1.equals(pkg);
+ default:
+ return false;
+ }
+ });
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> mLauncherApps.registerCallback(c0_1, h));
+ runWithCaller(LAUNCHER_2, USER_0, () -> mLauncherApps.registerCallback(c0_2, h));
+ runWithCaller(LAUNCHER_3, USER_0, () -> mLauncherApps.registerCallback(c0_3, h));
+ runWithCaller(LAUNCHER_4, USER_0, () -> mLauncherApps.registerCallback(c0_4, h));
+ runWithCaller(LAUNCHER_1, USER_P0, () -> mLauncherApps.registerCallback(cP0_1, h));
+ runWithCaller(LAUNCHER_1, USER_10, () -> mLauncherApps.registerCallback(c10_1, h));
+ runWithCaller(LAUNCHER_2, USER_10, () -> mLauncherApps.registerCallback(c10_2, h));
+ runWithCaller(LAUNCHER_1, USER_11, () -> mLauncherApps.registerCallback(c11_1, h));
+
+ // User 0.
+
+ resetAll(all);
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.deleteDynamicShortcut("x");
+ });
+ waitOnMainThread();
+
+ assertCallbackNotReceived(c0_1);
+ assertCallbackNotReceived(c0_3);
+ assertCallbackNotReceived(c0_4);
+ assertCallbackNotReceived(c10_1);
+ assertCallbackNotReceived(c10_2);
+ assertCallbackNotReceived(c11_1);
+ assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3");
+ assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4");
+
+ // User 0, different package.
+
+ resetAll(all);
+ runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+ mManager.deleteDynamicShortcut("x");
+ });
+ waitOnMainThread();
+
+ assertCallbackNotReceived(c0_1);
+ assertCallbackNotReceived(c0_3);
+ assertCallbackNotReceived(c0_4);
+ assertCallbackNotReceived(c10_1);
+ assertCallbackNotReceived(c10_2);
+ assertCallbackNotReceived(c11_1);
+ assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_3, "s1", "s2", "s3", "s4");
+ assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_3,
+ "s1", "s2", "s3", "s4", "s5", "s6");
+
+ // Work profile, but not running, so don't send notifications.
+
+ resetAll(all);
+ runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+ mManager.deleteDynamicShortcut("x");
+ });
+ waitOnMainThread();
+
+ assertCallbackNotReceived(c0_1);
+ assertCallbackNotReceived(c0_2);
+ assertCallbackNotReceived(c0_3);
+ assertCallbackNotReceived(c0_4);
+ assertCallbackNotReceived(cP0_1);
+ assertCallbackNotReceived(c10_1);
+ assertCallbackNotReceived(c10_2);
+ assertCallbackNotReceived(c11_1);
+
+ // Work profile, now running.
+
+ when(mMockUserManager.isUserRunning(anyInt())).thenReturn(false);
+ when(mMockUserManager.isUserRunning(eq(USER_P0))).thenReturn(true);
+
+ resetAll(all);
+ runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+ mManager.deleteDynamicShortcut("x");
+ });
+ waitOnMainThread();
+
+ assertCallbackNotReceived(c0_1);
+ assertCallbackNotReceived(c0_3);
+ assertCallbackNotReceived(c0_4);
+ assertCallbackNotReceived(c10_1);
+ assertCallbackNotReceived(c10_2);
+ assertCallbackNotReceived(c11_1);
+ assertCallbackReceived(c0_2, HANDLE_USER_P0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s5");
+ assertCallbackReceived(cP0_1, HANDLE_USER_P0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4");
+
+ // Normal secondary user.
+
+ when(mMockUserManager.isUserRunning(anyInt())).thenReturn(false);
+ when(mMockUserManager.isUserRunning(eq(USER_10))).thenReturn(true);
+
+ resetAll(all);
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ mManager.deleteDynamicShortcut("x");
+ });
+ waitOnMainThread();
+
+ assertCallbackNotReceived(c0_1);
+ assertCallbackNotReceived(c0_2);
+ assertCallbackNotReceived(c0_3);
+ assertCallbackNotReceived(c0_4);
+ assertCallbackNotReceived(cP0_1);
+ assertCallbackNotReceived(c10_2);
+ assertCallbackNotReceived(c11_1);
+ assertCallbackReceived(c10_1, HANDLE_USER_10, CALLING_PACKAGE_1,
+ "x1", "x2", "x3", "x4", "x5");
+ }
+
// === Test for persisting ===
public void testSaveAndLoadUser_empty() {
@@ -3979,6 +4207,10 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
}
}
+ shutdownServices();
+
+ deleteAllSavedFiles();
+
initService();
mService.applyRestore(payload, USER_0);
@@ -4064,6 +4296,31 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("x4", "x5", "x6", "x1"),
HANDLE_USER_10);
});
+
+ // Then remove some dynamic shortcuts.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list()));
+ });
+ runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"))));
+ });
}
private void prepareForBackupTest() {
@@ -4145,6 +4402,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
// Note doing a backup & restore again here shouldn't affect the result.
backupAndRestore();
+ // Change package signatures.
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1, "sigx", CALLING_PACKAGE_1);
addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4, LAUNCHER_1, "sigy");
@@ -4618,19 +4876,19 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
- "s1", "s2", "s3", "s4", "s5", "s6");
+ "s1", "s2", "s3");
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
"s1", "s2", "s3", "s4");
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
- "s1", "s2", "s3", "s4", "s5", "s6");
+ "s1", "s2", "s3");
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
"s1", "s2", "s3", "s4", "s5");
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
- "s1", "s2", "s3", "s4", "s5", "s6");
+ "s1", "s2", "s3");
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
"s1", "s2", "s3", "s4", "s5", "s6");
});
@@ -4642,7 +4900,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
});
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
- "s1", "s2", "s3", "s4", "s5", "s6");
+ "s1", "s2", "s3");
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
"s1", "s2", "s3", "s4", "s5", "s6");
});
@@ -4654,7 +4912,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
- "x1", "x2", "x3", "x4", "x5", "x6");
+ "x1", "x2", "x3");
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
"x4", "x5");
});
@@ -4757,7 +5015,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
"s1", "s4");
TestUtils.assertExpectException(
- SecurityException.class, "you need to be SYSTEM", () -> {
+ SecurityException.class, "unrelated profile", () -> {
mLauncherApps.getShortcuts(
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
});
@@ -4773,12 +5031,12 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10)
/* empty */);
TestUtils.assertExpectException(
- SecurityException.class, "you need to be SYSTEM", () -> {
+ SecurityException.class, "unrelated profile", () -> {
mLauncherApps.getShortcuts(
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0);
});
TestUtils.assertExpectException(
- SecurityException.class, "you need to be SYSTEM", () -> {
+ SecurityException.class, "unrelated profile", () -> {
mLauncherApps.getShortcuts(
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_P0);
});
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index beec40f8b0fa..0aeb96f52181 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -144,6 +144,7 @@ public class UsageStatsService extends SystemService implements
private long mLastAppIdleParoledTime;
private volatile boolean mPendingOneTimeCheckIdleStates;
+ private boolean mSystemServicesReady = false;
@GuardedBy("mLock")
private AppIdleHistory mAppIdleHistory;
@@ -232,6 +233,8 @@ public class UsageStatsService extends SystemService implements
if (mPendingOneTimeCheckIdleStates) {
postOneTimeCheckIdleStates();
}
+
+ mSystemServicesReady = true;
} else if (phase == PHASE_BOOT_COMPLETED) {
setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
}
@@ -810,28 +813,30 @@ public class UsageStatsService extends SystemService implements
// retain this for safety).
return false;
}
- try {
- // We allow all whitelisted apps, including those that don't want to be whitelisted
- // for idle mode, because app idle (aka app standby) is really not as big an issue
- // for controlling who participates vs. doze mode.
- if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
- return false;
+ if (mSystemServicesReady) {
+ try {
+ // We allow all whitelisted apps, including those that don't want to be whitelisted
+ // for idle mode, because app idle (aka app standby) is really not as big an issue
+ // for controlling who participates vs. doze mode.
+ if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
+ return false;
+ }
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- if (isActiveDeviceAdmin(packageName, userId)) {
- return false;
- }
+ if (isActiveDeviceAdmin(packageName, userId)) {
+ return false;
+ }
- if (isActiveNetworkScorer(packageName)) {
- return false;
- }
+ if (isActiveNetworkScorer(packageName)) {
+ return false;
+ }
- if (mAppWidgetManager != null
- && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
- return false;
+ if (mAppWidgetManager != null
+ && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
+ return false;
+ }
}
if (!isAppIdleUnfiltered(packageName, userId, elapsedRealtime)) {
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index 38ede87d2b85..46ce7a0a1aaf 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -127,6 +127,14 @@ public final class UsbMidiDevice implements Closeable {
public void setReceiver(MidiReceiver receiver) {
mReceiver = receiver;
}
+
+ @Override
+ public void onFlush() throws IOException {
+ MidiReceiver receiver = mReceiver;
+ if (receiver != null) {
+ receiver.flush();
+ }
+ }
}
public static UsbMidiDevice create(Context context, Bundle properties, int card, int device) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4fa8fe96a6a9..6eafb90fbfdb 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1433,25 +1433,6 @@ public class TelecomManager {
}
/**
- * Launches the {@link android.app.Activity} to manage blocked numbers.
- * <p> This method displays the UI to manage blocked numbers only if
- * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
- * {@code true} for the current user.
- * @deprecated Use {@link #createManageBlockedNumbersIntent()} instead.
- */
- // TODO: Delete this.
- public void launchManageBlockedNumbersActivity() {
- ITelecomService service = getTelecomService();
- if (service != null) {
- try {
- service.launchManageBlockedNumbersActivity(mContext.getPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecomService#manageBlockedNumbers", e);
- }
- }
- }
-
- /**
* Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
* launch the activity to manage blocked numbers.
* <p> The activity will display the UI to manage blocked numbers only if
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 3c250f1b54fd..871565de33c9 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -246,12 +246,6 @@ interface ITelecomService {
boolean setDefaultDialer(in String packageName);
/**
- * @see TelecomServiceImpl#launchManageBlockedNumbersActivity
- **/
- // TODO: Delete this.
- void launchManageBlockedNumbersActivity(in String callingPackageName);
-
- /**
* @see TelecomServiceImpl#createManageBlockedNumbersIntent
**/
Intent createManageBlockedNumbersIntent();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b482811a18f2..865af7821ac2 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3550,7 +3550,7 @@ public class TelephonyManager {
* @return the response of ISIM Authetification, or null if not available
* @hide
* @deprecated
- * @see getIccSimChallengeResponse with appType=PhoneConstants.APPTYPE_ISIM
+ * @see getIccAuthentication with appType=PhoneConstants.APPTYPE_ISIM
*/
public String getIsimChallengeResponse(String nonce){
try {
@@ -3566,21 +3566,60 @@ public class TelephonyManager {
}
}
+ // ICC SIM Application Types
+ public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
+ public static final int APPTYPE_USIM = PhoneConstants.APPTYPE_USIM;
+ public static final int APPTYPE_RUIM = PhoneConstants.APPTYPE_RUIM;
+ public static final int APPTYPE_CSIM = PhoneConstants.APPTYPE_CSIM;
+ public static final int APPTYPE_ISIM = PhoneConstants.APPTYPE_ISIM;
+ // authContext (parameter P2) when doing SIM challenge,
+ // per 3GPP TS 31.102 (Section 7.1.2)
+ public static final int AUTHTYPE_EAP_SIM = PhoneConstants.AUTH_CONTEXT_EAP_SIM;
+ public static final int AUTHTYPE_EAP_AKA = PhoneConstants.AUTH_CONTEXT_EAP_AKA;
+
/**
- * Returns the response of SIM Authentication through RIL.
- * Returns null if the Authentication hasn't been successful
- * @param subId subscription ID to be queried
- * @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
- * @param data authentication challenge data
- * @return the response of SIM Authentication, or null if not available
- * @hide
+ * Returns the response of authentication for the default subscription.
+ * Returns null if the authentication hasn't been successful
+ *
+ * <p>Requires that the calling app has carrier privileges or READ_PRIVILEGED_PHONE_STATE
+ * permission.
+ *
+ * @param appType the icc application type, like {@link #APPTYPE_USIM}
+ * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
+ * {@link #AUTHTYPE_EAP_SIM}
+ * @param data authentication challenge data, base64 encoded.
+ * See 3GPP TS 31.102 7.1.2 for more details.
+ * @return the response of authentication, or null if not available
+ *
+ * @see #hasCarrierPrivileges
*/
- public String getIccSimChallengeResponse(int subId, int appType, String data) {
+ public String getIccAuthentication(int appType, int authType, String data) {
+ return getIccAuthentication(getDefaultSubscription(), appType, authType, data);
+ }
+
+ /**
+ * Returns the response of USIM Authentication for specified subId.
+ * Returns null if the authentication hasn't been successful
+ *
+ * <p>Requires that the calling app has carrier privileges.
+ *
+ * @param subId subscription ID used for authentication
+ * @param appType the icc application type, like {@link #APPTYPE_USIM}
+ * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
+ * {@link #AUTHTYPE_EAP_SIM}
+ * @param data authentication challenge data, base64 encoded.
+ * See 3GPP TS 31.102 7.1.2 for more details.
+ * @return the response of authentication, or null if not available
+ *
+ * @see #hasCarrierPrivileges
+ */
+
+ public String getIccAuthentication(int subId, int appType, int authType, String data) {
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getIccSimChallengeResponse(subId, appType, data);
+ return info.getIccSimChallengeResponse(subId, appType, authType, data);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3599,9 +3638,10 @@ public class TelephonyManager {
* @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
* @param data authentication challenge data
* @return the response of SIM Authentication, or null if not available
+ * @hide
*/
public String getIccSimChallengeResponse(int appType, String data) {
- return getIccSimChallengeResponse(getDefaultSubscription(), appType, data);
+ return getIccAuthentication(getDefaultSubscription(), appType, AUTHTYPE_EAP_SIM, data);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index dc2b297f6dbe..02baa3454536 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -196,8 +196,9 @@ interface IPhoneSubInfo {
*
* @param subId subscription ID to be queried
* @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
+ * @param authType Authentication type, see PhoneConstants#AUTHTYPE_xxx
* @param data authentication challenge data
* @return challenge response
*/
- String getIccSimChallengeResponse(int subId, int appType, String data);
+ String getIccSimChallengeResponse(int subId, int appType, int authType, String data);
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index ecd89eda4577..1680fe33ead7 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -202,4 +202,10 @@ public class PhoneConstants {
public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0;
public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1;
public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER;
+
+ // authContext (parameter P2) when doing SIM challenge,
+ // per 3GPP TS 31.102 (Section 7.1.2)
+ public static final int AUTH_CONTEXT_EAP_SIM = 128;
+ public static final int AUTH_CONTEXT_EAP_AKA = 129;
+ public static final int AUTH_CONTEXT_UNDEFINED = -1;
}
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 641c34bd2dda..d631f3531127 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -33,7 +33,7 @@ static const char* kNoCompressExt[] = {
".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
- ".amr", ".awb", ".wma", ".wmv", ".webm"
+ ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"
};
/* fwd decls, so I can write this downward */
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 876a422a2678..ef11d662b2ce 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -66,6 +66,7 @@ sources := \
ResourceValues.cpp \
SdkConstants.cpp \
StringPool.cpp \
+ xml/XmlActionExecutor.cpp \
xml/XmlDom.cpp \
xml/XmlPullParser.cpp \
xml/XmlUtil.cpp
@@ -107,6 +108,7 @@ testSources := \
SdkConstants_test.cpp \
StringPool_test.cpp \
ValueVisitor_test.cpp \
+ xml/XmlActionExecutor_test.cpp \
xml/XmlDom_test.cpp \
xml/XmlPullParser_test.cpp \
xml/XmlUtil_test.cpp
@@ -140,7 +142,7 @@ else
endif
cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG
-cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
+cppFlags := -std=c++14 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
protoIncludes := $(call generated-sources-dir-for,STATIC_LIBRARIES,libaapt2,HOST)
# ==========================================================
diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h
index ab4d284516e1..e86f2a8830e8 100644
--- a/tools/aapt2/Diagnostics.h
+++ b/tools/aapt2/Diagnostics.h
@@ -21,6 +21,7 @@
#include "util/StringPiece.h"
#include "util/Util.h"
+#include <android-base/macros.h>
#include <iostream>
#include <sstream>
#include <string>
@@ -46,7 +47,11 @@ public:
DiagMessage(const Source& src) : mSource(src) {
}
- template <typename T> DiagMessage& operator<<(const T& value) {
+ DiagMessage(size_t line) : mSource(Source().withLine(line)) {
+ }
+
+ template <typename T>
+ DiagMessage& operator<<(const T& value) {
mMessage << value;
return *this;
}
@@ -59,36 +64,82 @@ public:
struct IDiagnostics {
virtual ~IDiagnostics() = default;
- virtual void error(const DiagMessage& message) = 0;
- virtual void warn(const DiagMessage& message) = 0;
- virtual void note(const DiagMessage& message) = 0;
-};
+ enum class Level {
+ Note,
+ Warn,
+ Error
+ };
-struct StdErrDiagnostics : public IDiagnostics {
- size_t mNumErrors = 0;
+ virtual void log(Level level, DiagMessageActual& actualMsg) = 0;
- void emit(const DiagMessage& msg, const char* tag) {
- DiagMessageActual actual = msg.build();
- if (!actual.source.path.empty()) {
- std::cerr << actual.source << ": ";
- }
- std::cerr << tag << actual.message << "." << std::endl;
+ virtual void error(const DiagMessage& message) {
+ DiagMessageActual actual = message.build();
+ log(Level::Error, actual);
+ }
+
+ virtual void warn(const DiagMessage& message) {
+ DiagMessageActual actual = message.build();
+ log(Level::Warn, actual);
+ }
+
+ virtual void note(const DiagMessage& message) {
+ DiagMessageActual actual = message.build();
+ log(Level::Note, actual);
}
+};
- void error(const DiagMessage& msg) override {
- if (mNumErrors < 20) {
- emit(msg, "error: ");
+class StdErrDiagnostics : public IDiagnostics {
+public:
+ StdErrDiagnostics() = default;
+
+ void log(Level level, DiagMessageActual& actualMsg) override {
+ const char* tag;
+
+ switch (level) {
+ case Level::Error:
+ mNumErrors++;
+ if (mNumErrors > 20) {
+ return;
+ }
+ tag = "error";
+ break;
+
+ case Level::Warn:
+ tag = "warn";
+ break;
+
+ case Level::Note:
+ tag = "note";
+ break;
}
- mNumErrors++;
+
+ if (!actualMsg.source.path.empty()) {
+ std::cerr << actualMsg.source << ": ";
+ }
+ std::cerr << tag << ": " << actualMsg.message << "." << std::endl;
}
- void warn(const DiagMessage& msg) override {
- emit(msg, "warn: ");
+private:
+ size_t mNumErrors = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(StdErrDiagnostics);
+};
+
+class SourcePathDiagnostics : public IDiagnostics {
+public:
+ SourcePathDiagnostics(const Source& src, IDiagnostics* diag) : mSource(src), mDiag(diag) {
}
- void note(const DiagMessage& msg) override {
- emit(msg, "note: ");
+ void log(Level level, DiagMessageActual& actualMsg) override {
+ actualMsg.source.path = mSource.path;
+ mDiag->log(level, actualMsg);
}
+
+private:
+ Source mSource;
+ IDiagnostics* mDiag;
+
+ DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics);
};
} // namespace aapt
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index 180bd11275df..d6c52ab83d93 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -28,33 +28,23 @@
namespace aapt {
-struct ResourceTableTest : public ::testing::Test {
- struct EmptyDiagnostics : public IDiagnostics {
- void error(const DiagMessage& msg) override {}
- void warn(const DiagMessage& msg) override {}
- void note(const DiagMessage& msg) override {}
- };
-
- EmptyDiagnostics mDiagnostics;
-};
-
-TEST_F(ResourceTableTest, FailToAddResourceWithBadName) {
+TEST(ResourceTableTest, FailToAddResourceWithBadName) {
ResourceTable table;
EXPECT_FALSE(table.addResource(
ResourceNameRef(u"android", ResourceType::kId, u"hey,there"),
ConfigDescription{}, "",
test::ValueBuilder<Id>().setSource("test.xml", 21u).build(),
- &mDiagnostics));
+ test::getDiagnostics()));
EXPECT_FALSE(table.addResource(
ResourceNameRef(u"android", ResourceType::kId, u"hey:there"),
ConfigDescription{}, "",
test::ValueBuilder<Id>().setSource("test.xml", 21u).build(),
- &mDiagnostics));
+ test::getDiagnostics()));
}
-TEST_F(ResourceTableTest, AddOneResource) {
+TEST(ResourceTableTest, AddOneResource) {
ResourceTable table;
EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/id"),
@@ -62,12 +52,12 @@ TEST_F(ResourceTableTest, AddOneResource) {
"",
test::ValueBuilder<Id>()
.setSource("test/path/file.xml", 23u).build(),
- &mDiagnostics));
+ test::getDiagnostics()));
ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id"));
}
-TEST_F(ResourceTableTest, AddMultipleResources) {
+TEST(ResourceTableTest, AddMultipleResources) {
ResourceTable table;
ConfigDescription config;
@@ -79,21 +69,21 @@ TEST_F(ResourceTableTest, AddMultipleResources) {
config,
"",
test::ValueBuilder<Id>().setSource("test/path/file.xml", 10u).build(),
- &mDiagnostics));
+ test::getDiagnostics()));
EXPECT_TRUE(table.addResource(
test::parseNameOrDie(u"@android:attr/id"),
config,
"",
test::ValueBuilder<Id>().setSource("test/path/file.xml", 12u).build(),
- &mDiagnostics));
+ test::getDiagnostics()));
EXPECT_TRUE(table.addResource(
test::parseNameOrDie(u"@android:string/ok"),
config,
"",
test::ValueBuilder<Id>().setSource("test/path/file.xml", 14u).build(),
- &mDiagnostics));
+ test::getDiagnostics()));
EXPECT_TRUE(table.addResource(
test::parseNameOrDie(u"@android:string/ok"),
@@ -102,7 +92,7 @@ TEST_F(ResourceTableTest, AddMultipleResources) {
test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
.setSource("test/path/file.xml", 20u)
.build(),
- &mDiagnostics));
+ test::getDiagnostics()));
ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/layout_width"));
ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id"));
@@ -111,37 +101,37 @@ TEST_F(ResourceTableTest, AddMultipleResources) {
languageConfig));
}
-TEST_F(ResourceTableTest, OverrideWeakResourceValue) {
+TEST(ResourceTableTest, OverrideWeakResourceValue) {
ResourceTable table;
ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{},
- "", util::make_unique<Attribute>(true), &mDiagnostics));
+ "", util::make_unique<Attribute>(true), test::getDiagnostics()));
Attribute* attr = test::getValue<Attribute>(&table, u"@android:attr/foo");
ASSERT_NE(nullptr, attr);
EXPECT_TRUE(attr->isWeak());
ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{},
- "", util::make_unique<Attribute>(false), &mDiagnostics));
+ "", util::make_unique<Attribute>(false), test::getDiagnostics()));
attr = test::getValue<Attribute>(&table, u"@android:attr/foo");
ASSERT_NE(nullptr, attr);
EXPECT_FALSE(attr->isWeak());
}
-TEST_F(ResourceTableTest, ProductVaryingValues) {
+TEST(ResourceTableTest, ProductVaryingValues) {
ResourceTable table;
EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"),
test::parseConfigOrDie("land"),
"tablet",
util::make_unique<Id>(),
- &mDiagnostics));
+ test::getDiagnostics()));
EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"),
test::parseConfigOrDie("land"),
"phone",
util::make_unique<Id>(),
- &mDiagnostics));
+ test::getDiagnostics()));
EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/foo",
test::parseConfigOrDie("land"),
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 2d076c2d5a66..092bab241bba 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -437,6 +437,15 @@ bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate, st
return generate(packageNameToGenerate, packageNameToGenerate, out);
}
+static void appendJavaDocAnnotations(const std::vector<std::string>& annotations,
+ AnnotationProcessor* processor) {
+ for (const std::string& annotation : annotations) {
+ std::string properAnnotation = "@";
+ properAnnotation += annotation;
+ processor->appendComment(properAnnotation);
+ }
+}
+
bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate,
const StringPiece16& outPackageName, std::ostream* out) {
@@ -477,14 +486,17 @@ bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate,
mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) {
// When generating a public R class, we don't want Styleable to be part of the API.
// It is only emitted for documentation purposes.
- AnnotationProcessor* processor = classDef->getCommentBuilder();
- processor->appendComment("@doconly");
+ classDef->getCommentBuilder()->appendComment("@doconly");
}
+ appendJavaDocAnnotations(mOptions.javadocAnnotations, classDef->getCommentBuilder());
+
rClass.addMember(std::move(classDef));
}
}
+ appendJavaDocAnnotations(mOptions.javadocAnnotations, rClass.getCommentBuilder());
+
if (!ClassDefinition::writeJavaFile(&rClass, util::utf16ToUtf8(outPackageName),
mOptions.useFinal, out)) {
return false;
@@ -494,6 +506,4 @@ bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate,
return true;
}
-
-
} // namespace aapt
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index b594a88728f4..77e0ed76143a 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -44,6 +44,11 @@ struct JavaClassGeneratorOptions {
};
SymbolTypes types = SymbolTypes::kAll;
+
+ /**
+ * A list of JavaDoc annotations to add to the comments of all generated classes.
+ */
+ std::vector<std::string> javadocAnnotations;
};
/*
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 8c10fbb6e38a..8c8bffafdc45 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -66,6 +66,7 @@ struct LinkOptions {
bool staticLib = false;
bool noStaticLibPackages = false;
bool generateNonFinalIds = false;
+ std::vector<std::string> javadocAnnotations;
bool outputToDirectory = false;
bool autoAddOverlay = false;
bool doNotCompressAnything = false;
@@ -775,6 +776,13 @@ public:
return true;
}
+ // Add any JavaDoc annotations to the generated class.
+ for (const std::string& annotation : mOptions.javadocAnnotations) {
+ std::string properAnnotation = "@";
+ properAnnotation += annotation;
+ manifestClass->getCommentBuilder()->appendComment(properAnnotation);
+ }
+
const std::string packageUtf8 = util::utf16ToUtf8(mContext->getCompilationPackage());
std::string outPath = mOptions.generateJavaClassPath.value();
@@ -1292,6 +1300,7 @@ public:
if (mOptions.generateJavaClassPath) {
JavaClassGeneratorOptions options;
options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+ options.javadocAnnotations = mOptions.javadocAnnotations;
if (mOptions.staticLib || mOptions.generateNonFinalIds) {
options.useFinal = false;
@@ -1432,6 +1441,8 @@ int link(const std::vector<StringPiece>& args) {
&customJavaPackage)
.optionalFlagList("--extra-packages", "Generate the same R.java but with different "
"package names", &extraJavaPackages)
+ .optionalFlagList("--add-javadoc-annotation", "Adds a JavaDoc annotation to all "
+ "generated Java classes", &options.javadocAnnotations)
.optionalSwitch("--auto-add-overlay", "Allows the addition of new resources in "
"overlays without <add-resource> tags", &options.autoAddOverlay)
.optionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml",
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 9baf1d86795c..3779638590be 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -17,66 +17,199 @@
#include "ResourceUtils.h"
#include "link/ManifestFixer.h"
#include "util/Util.h"
+#include "xml/XmlActionExecutor.h"
#include "xml/XmlDom.h"
namespace aapt {
-static bool verifyManifest(IAaptContext* context, const Source& source, xml::Element* manifestEl) {
- xml::Attribute* attr = manifestEl->findAttribute({}, u"package");
- if (!attr) {
- context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
- << "missing 'package' attribute");
- } else if (ResourceUtils::isReference(attr->value)) {
- context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
- << "value for attribute 'package' must not be a "
- "reference");
- } else if (!util::isJavaPackageName(attr->value)) {
- context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
- << "invalid package name '" << attr->value << "'");
- } else {
- return true;
+/**
+ * This is how PackageManager builds class names from AndroidManifest.xml entries.
+ */
+static bool nameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
+ SourcePathDiagnostics* diag) {
+ std::u16string className = attr->value;
+ if (className.find(u'.') == std::u16string::npos) {
+ // There is no '.', so add one to the beginning.
+ className = u".";
+ className += attr->value;
}
- return false;
-}
-static bool includeVersionName(IAaptContext* context, const Source& source,
- const StringPiece16& versionName, xml::Element* manifestEl) {
- if (manifestEl->findAttribute(xml::kSchemaAndroid, u"versionName")) {
- return true;
+ // We allow unqualified class names (ie: .HelloActivity)
+ // Since we don't know the package name, we can just make a fake one here and
+ // the test will be identical as long as the real package name is valid too.
+ Maybe<std::u16string> fullyQualifiedClassName =
+ util::getFullyQualifiedClassName(u"a", className);
+
+ StringPiece16 qualifiedClassName = fullyQualifiedClassName
+ ? fullyQualifiedClassName.value() : className;
+ if (!util::isJavaClassName(qualifiedClassName)) {
+ diag->error(DiagMessage(el->lineNumber)
+ << "attribute 'android:name' in <"
+ << el->name << "> tag must be a valid Java class name");
+ return false;
}
+ return true;
+}
- manifestEl->attributes.push_back(xml::Attribute{
- xml::kSchemaAndroid, u"versionName", versionName.toString() });
+static bool optionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
+ if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) {
+ return nameIsJavaClassName(el, attr, diag);
+ }
return true;
}
-static bool includeVersionCode(IAaptContext* context, const Source& source,
- const StringPiece16& versionCode, xml::Element* manifestEl) {
- if (manifestEl->findAttribute(xml::kSchemaAndroid, u"versionCode")) {
- return true;
+static bool requiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
+ if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) {
+ return nameIsJavaClassName(el, attr, diag);
}
+ diag->error(DiagMessage(el->lineNumber)
+ << "<" << el->name << "> is missing attribute 'android:name'");
+ return false;
+}
- manifestEl->attributes.push_back(xml::Attribute{
- xml::kSchemaAndroid, u"versionCode", versionCode.toString() });
+static bool verifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
+ xml::Attribute* attr = el->findAttribute({}, u"package");
+ if (!attr) {
+ diag->error(DiagMessage(el->lineNumber) << "<manifest> tag is missing 'package' attribute");
+ return false;
+ } else if (ResourceUtils::isReference(attr->value)) {
+ diag->error(DiagMessage(el->lineNumber)
+ << "attribute 'package' in <manifest> tag must not be a reference");
+ return false;
+ } else if (!util::isJavaPackageName(attr->value)) {
+ diag->error(DiagMessage(el->lineNumber)
+ << "attribute 'package' in <manifest> tag is not a valid Java package name: '"
+ << attr->value << "'");
+ return false;
+ }
return true;
}
-static bool fixUsesSdk(IAaptContext* context, const Source& source, xml::Element* el,
- const ManifestFixerOptions& options) {
- if (options.minSdkVersionDefault &&
- el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) {
- // There was no minSdkVersion defined and we have a default to assign.
- el->attributes.push_back(xml::Attribute{
- xml::kSchemaAndroid, u"minSdkVersion", options.minSdkVersionDefault.value() });
+bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag) {
+ // First verify some options.
+ if (mOptions.renameManifestPackage) {
+ if (!util::isJavaPackageName(mOptions.renameManifestPackage.value())) {
+ diag->error(DiagMessage() << "invalid manifest package override '"
+ << mOptions.renameManifestPackage.value() << "'");
+ return false;
+ }
}
- if (options.targetSdkVersionDefault &&
- el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) {
- // There was no targetSdkVersion defined and we have a default to assign.
- el->attributes.push_back(xml::Attribute{
- xml::kSchemaAndroid, u"targetSdkVersion",
- options.targetSdkVersionDefault.value() });
+ if (mOptions.renameInstrumentationTargetPackage) {
+ if (!util::isJavaPackageName(mOptions.renameInstrumentationTargetPackage.value())) {
+ diag->error(DiagMessage() << "invalid instrumentation target package override '"
+ << mOptions.renameInstrumentationTargetPackage.value() << "'");
+ return false;
+ }
}
+
+ // Common intent-filter actions.
+ xml::XmlNodeAction intentFilterAction;
+ intentFilterAction[u"action"];
+ intentFilterAction[u"category"];
+ intentFilterAction[u"data"];
+
+ // Common meta-data actions.
+ xml::XmlNodeAction metaDataAction;
+
+ // Manifest actions.
+ xml::XmlNodeAction& manifestAction = (*executor)[u"manifest"];
+ manifestAction.action(verifyManifest);
+ manifestAction.action([&](xml::Element* el) -> bool {
+ if (mOptions.versionNameDefault) {
+ if (el->findAttribute(xml::kSchemaAndroid, u"versionName") == nullptr) {
+ el->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid,
+ u"versionName",
+ mOptions.versionNameDefault.value() });
+ }
+ }
+
+ if (mOptions.versionCodeDefault) {
+ if (el->findAttribute(xml::kSchemaAndroid, u"versionCode") == nullptr) {
+ el->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid,
+ u"versionCode",
+ mOptions.versionCodeDefault.value() });
+ }
+ }
+ return true;
+ });
+
+ // Uses-sdk actions.
+ manifestAction[u"uses-sdk"].action([&](xml::Element* el) -> bool {
+ if (mOptions.minSdkVersionDefault &&
+ el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) {
+ // There was no minSdkVersion defined and we have a default to assign.
+ el->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid, u"minSdkVersion",
+ mOptions.minSdkVersionDefault.value() });
+ }
+
+ if (mOptions.targetSdkVersionDefault &&
+ el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) {
+ // There was no targetSdkVersion defined and we have a default to assign.
+ el->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid, u"targetSdkVersion",
+ mOptions.targetSdkVersionDefault.value() });
+ }
+ return true;
+ });
+
+ // Instrumentation actions.
+ manifestAction[u"instrumentation"].action([&](xml::Element* el) -> bool {
+ if (!mOptions.renameInstrumentationTargetPackage) {
+ return true;
+ }
+
+ if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"targetPackage")) {
+ attr->value = mOptions.renameInstrumentationTargetPackage.value();
+ }
+ return true;
+ });
+
+ manifestAction[u"eat-comment"];
+ manifestAction[u"protected-broadcast"];
+ manifestAction[u"uses-permission"];
+ manifestAction[u"permission"];
+ manifestAction[u"permission-tree"];
+ manifestAction[u"permission-group"];
+
+ manifestAction[u"uses-configuration"];
+ manifestAction[u"uses-feature"];
+ manifestAction[u"uses-library"];
+ manifestAction[u"supports-screens"];
+ manifestAction[u"compatible-screens"];
+ manifestAction[u"supports-gl-texture"];
+
+ // Application actions.
+ xml::XmlNodeAction& applicationAction = (*executor)[u"manifest"][u"application"];
+ applicationAction.action(optionalNameIsJavaClassName);
+
+ // Activity actions.
+ applicationAction[u"activity"].action(requiredNameIsJavaClassName);
+ applicationAction[u"activity"][u"intent-filter"] = intentFilterAction;
+ applicationAction[u"activity"][u"meta-data"] = metaDataAction;
+
+ // Activity alias actions.
+ applicationAction[u"activity-alias"][u"intent-filter"] = intentFilterAction;
+ applicationAction[u"activity-alias"][u"meta-data"] = metaDataAction;
+
+ // Service actions.
+ applicationAction[u"service"].action(requiredNameIsJavaClassName);
+ applicationAction[u"service"][u"intent-filter"] = intentFilterAction;
+ applicationAction[u"service"][u"meta-data"] = metaDataAction;
+
+ // Receiver actions.
+ applicationAction[u"receiver"].action(requiredNameIsJavaClassName);
+ applicationAction[u"receiver"][u"intent-filter"] = intentFilterAction;
+ applicationAction[u"receiver"][u"meta-data"] = metaDataAction;
+
+ // Provider actions.
+ applicationAction[u"provider"].action(requiredNameIsJavaClassName);
+ applicationAction[u"provider"][u"grant-uri-permissions"];
+ applicationAction[u"provider"][u"meta-data"] = metaDataAction;
+ applicationAction[u"provider"][u"path-permissions"];
return true;
}
@@ -103,14 +236,7 @@ private:
StringPiece16 mPackage;
};
-static bool renameManifestPackage(IAaptContext* context, const Source& source,
- const StringPiece16& packageOverride, xml::Element* manifestEl) {
- if (!util::isJavaPackageName(packageOverride)) {
- context->getDiagnostics()->error(DiagMessage() << "invalid manifest package override '"
- << packageOverride << "'");
- return false;
- }
-
+static bool renameManifestPackage(const StringPiece16& packageOverride, xml::Element* manifestEl) {
xml::Attribute* attr = manifestEl->findAttribute({}, u"package");
// We've already verified that the manifest element is present, with a package name specified.
@@ -124,32 +250,6 @@ static bool renameManifestPackage(IAaptContext* context, const Source& source,
return true;
}
-static bool renameInstrumentationTargetPackage(IAaptContext* context, const Source& source,
- const StringPiece16& packageOverride,
- xml::Element* manifestEl) {
- if (!util::isJavaPackageName(packageOverride)) {
- context->getDiagnostics()->error(DiagMessage()
- << "invalid instrumentation target package override '"
- << packageOverride << "'");
- return false;
- }
-
- xml::Element* instrumentationEl = manifestEl->findChild({}, u"instrumentation");
- if (!instrumentationEl) {
- // No error if there is no work to be done.
- return true;
- }
-
- xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, u"targetPackage");
- if (!attr) {
- // No error if there is no work to be done.
- return true;
- }
-
- attr->value = packageOverride.toString();
- return true;
-}
-
bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) {
xml::Element* root = xml::findRootElement(doc->root.get());
if (!root || !root->namespaceUri.empty() || root->name != u"manifest") {
@@ -158,59 +258,31 @@ bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) {
return false;
}
- if (!verifyManifest(context, doc->file.source, root)) {
- return false;
+ if ((mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault)
+ && root->findChild({}, u"uses-sdk") == nullptr) {
+ // Auto insert a <uses-sdk> element.
+ std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>();
+ usesSdk->name = u"uses-sdk";
+ root->addChild(std::move(usesSdk));
}
- if (mOptions.versionCodeDefault) {
- if (!includeVersionCode(context, doc->file.source, mOptions.versionCodeDefault.value(),
- root)) {
- return false;
- }
+ xml::XmlActionExecutor executor;
+ if (!buildRules(&executor, context->getDiagnostics())) {
+ return false;
}
- if (mOptions.versionNameDefault) {
- if (!includeVersionName(context, doc->file.source, mOptions.versionNameDefault.value(),
- root)) {
- return false;
- }
+ if (!executor.execute(xml::XmlActionExecutorPolicy::Whitelist, context->getDiagnostics(),
+ doc)) {
+ return false;
}
if (mOptions.renameManifestPackage) {
- // Rename manifest package.
- if (!renameManifestPackage(context, doc->file.source,
- mOptions.renameManifestPackage.value(), root)) {
- return false;
- }
- }
-
- if (mOptions.renameInstrumentationTargetPackage) {
- if (!renameInstrumentationTargetPackage(context, doc->file.source,
- mOptions.renameInstrumentationTargetPackage.value(),
- root)) {
+ // Rename manifest package outside of the XmlActionExecutor.
+ // We need to extract the old package name and FullyQualify all class names.
+ if (!renameManifestPackage(mOptions.renameManifestPackage.value(), root)) {
return false;
}
}
-
- bool foundUsesSdk = false;
- for (xml::Element* el : root->getChildElements()) {
- if (!el->namespaceUri.empty()) {
- continue;
- }
-
- if (el->name == u"uses-sdk") {
- foundUsesSdk = true;
- fixUsesSdk(context, doc->file.source, el, mOptions);
- }
- }
-
- if (!foundUsesSdk && (mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault)) {
- std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>();
- usesSdk->name = u"uses-sdk";
- fixUsesSdk(context, doc->file.source, usesSdk.get(), mOptions);
- root->addChild(std::move(usesSdk));
- }
-
return true;
}
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index b8d9c833ff05..4d9356a933c2 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -19,6 +19,7 @@
#include "process/IResourceTableConsumer.h"
#include "util/Maybe.h"
+#include "xml/XmlActionExecutor.h"
#include "xml/XmlDom.h"
#include <string>
@@ -38,13 +39,17 @@ struct ManifestFixerOptions {
* Verifies that the manifest is correctly formed and inserts defaults
* where specified with ManifestFixerOptions.
*/
-struct ManifestFixer : public IXmlResourceConsumer {
- ManifestFixerOptions mOptions;
-
+class ManifestFixer : public IXmlResourceConsumer {
+public:
ManifestFixer(const ManifestFixerOptions& options) : mOptions(options) {
}
bool consume(IAaptContext* context, xml::XmlResource* doc) override;
+
+private:
+ bool buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag);
+
+ ManifestFixerOptions mOptions;
};
} // namespace aapt
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 18c47dff33ec..f993720b9566 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -166,9 +166,9 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
- <application name=".MainApplication" text="hello">
- <activity name=".activity.Start" />
- <receiver name="com.google.android.Receiver" />
+ <application android:name=".MainApplication" text="hello">
+ <activity android:name=".activity.Start" />
+ <receiver android:name="com.google.android.Receiver" />
</application>
</manifest>)EOF", options);
ASSERT_NE(nullptr, doc);
@@ -185,7 +185,7 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
xml::Element* applicationEl = manifestEl->findChild({}, u"application");
ASSERT_NE(nullptr, applicationEl);
- attr = applicationEl->findAttribute({}, u"name");
+ attr = applicationEl->findAttribute(xml::kSchemaAndroid, u"name");
ASSERT_NE(nullptr, attr);
EXPECT_EQ(std::u16string(u"android.MainApplication"), attr->value);
@@ -197,14 +197,14 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
el = applicationEl->findChild({}, u"activity");
ASSERT_NE(nullptr, el);
- attr = el->findAttribute({}, u"name");
+ attr = el->findAttribute(xml::kSchemaAndroid, u"name");
ASSERT_NE(nullptr, el);
EXPECT_EQ(std::u16string(u"android.activity.Start"), attr->value);
el = applicationEl->findChild({}, u"receiver");
ASSERT_NE(nullptr, el);
- attr = el->findAttribute({}, u"name");
+ attr = el->findAttribute(xml::kSchemaAndroid, u"name");
ASSERT_NE(nullptr, el);
EXPECT_EQ(std::u16string(u"com.google.android.Receiver"), attr->value);
}
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 8c56ebc67b32..8eb4bc88168d 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -238,7 +238,7 @@ inline std::unique_ptr<xml::XmlResource> buildXmlDom(const StringPiece& str) {
std::stringstream in;
in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str;
StdErrDiagnostics diag;
- std::unique_ptr<xml::XmlResource> doc = xml::inflate(&in, &diag, {});
+ std::unique_ptr<xml::XmlResource> doc = xml::inflate(&in, &diag, Source("test.xml"));
assert(doc);
return doc;
}
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 348c32a04e88..faccd47783ff 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -41,15 +41,20 @@ namespace aapt {
namespace test {
struct DummyDiagnosticsImpl : public IDiagnostics {
- void error(const DiagMessage& message) override {
- DiagMessageActual actual = message.build();
- std::cerr << actual.source << ": error: " << actual.message << "." << std::endl;
- }
- void warn(const DiagMessage& message) override {
- DiagMessageActual actual = message.build();
- std::cerr << actual.source << ": warn: " << actual.message << "." << std::endl;
+ void log(Level level, DiagMessageActual& actualMsg) override {
+ switch (level) {
+ case Level::Note:
+ return;
+
+ case Level::Warn:
+ std::cerr << actualMsg.source << ": warn: " << actualMsg.message << "." << std::endl;
+ break;
+
+ case Level::Error:
+ std::cerr << actualMsg.source << ": error: " << actualMsg.message << "." << std::endl;
+ break;
+ }
}
- void note(const DiagMessage& message) override {}
};
inline IDiagnostics* getDiagnostics() {
diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp
new file mode 100644
index 000000000000..0ef67eaf3dc5
--- /dev/null
+++ b/tools/aapt2/xml/XmlActionExecutor.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xml/XmlActionExecutor.h"
+
+namespace aapt {
+namespace xml {
+
+static bool wrapperOne(XmlNodeAction::ActionFunc& f, Element* el, SourcePathDiagnostics*) {
+ return f(el);
+}
+
+static bool wrapperTwo(XmlNodeAction::ActionFuncWithDiag& f, Element* el,
+ SourcePathDiagnostics* diag) {
+ return f(el, diag);
+}
+
+void XmlNodeAction::action(XmlNodeAction::ActionFunc f) {
+ mActions.emplace_back(std::bind(wrapperOne, std::move(f),
+ std::placeholders::_1,
+ std::placeholders::_2));
+}
+
+void XmlNodeAction::action(XmlNodeAction::ActionFuncWithDiag f) {
+ mActions.emplace_back(std::bind(wrapperTwo, std::move(f),
+ std::placeholders::_1,
+ std::placeholders::_2));
+}
+
+static void printElementToDiagMessage(const Element* el, DiagMessage* msg) {
+ *msg << "<";
+ if (!el->namespaceUri.empty()) {
+ *msg << el->namespaceUri << ":";
+ }
+ *msg << el->name << ">";
+}
+
+bool XmlNodeAction::execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag,
+ Element* el) const {
+ bool error = false;
+ for (const ActionFuncWithDiag& action : mActions) {
+ error |= !action(el, diag);
+ }
+
+ for (Element* childEl : el->getChildElements()) {
+ if (childEl->namespaceUri.empty()) {
+ std::map<std::u16string, XmlNodeAction>::const_iterator iter =
+ mMap.find(childEl->name);
+ if (iter != mMap.end()) {
+ error |= !iter->second.execute(policy, diag, childEl);
+ continue;
+ }
+ }
+
+ if (policy == XmlActionExecutorPolicy::Whitelist) {
+ DiagMessage errorMsg(childEl->lineNumber);
+ errorMsg << "unknown element ";
+ printElementToDiagMessage(childEl, &errorMsg);
+ errorMsg << " found";
+ diag->error(errorMsg);
+ error = true;
+ }
+ }
+ return !error;
+}
+
+bool XmlActionExecutor::execute(XmlActionExecutorPolicy policy, IDiagnostics* diag,
+ XmlResource* doc) const {
+ SourcePathDiagnostics sourceDiag(doc->file.source, diag);
+
+ Element* el = findRootElement(doc);
+ if (!el) {
+ if (policy == XmlActionExecutorPolicy::Whitelist) {
+ sourceDiag.error(DiagMessage() << "no root XML tag found");
+ return false;
+ }
+ return true;
+ }
+
+ if (el->namespaceUri.empty()) {
+ std::map<std::u16string, XmlNodeAction>::const_iterator iter = mMap.find(el->name);
+ if (iter != mMap.end()) {
+ return iter->second.execute(policy, &sourceDiag, el);
+ }
+ }
+
+ if (policy == XmlActionExecutorPolicy::Whitelist) {
+ DiagMessage errorMsg(el->lineNumber);
+ errorMsg << "unknown element ";
+ printElementToDiagMessage(el, &errorMsg);
+ errorMsg << " found";
+ sourceDiag.error(errorMsg);
+ return false;
+ }
+ return true;
+}
+
+} // namespace xml
+} // namespace aapt
diff --git a/tools/aapt2/xml/XmlActionExecutor.h b/tools/aapt2/xml/XmlActionExecutor.h
new file mode 100644
index 000000000000..36b94dbfde05
--- /dev/null
+++ b/tools/aapt2/xml/XmlActionExecutor.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_XML_XMLPATTERN_H
+#define AAPT_XML_XMLPATTERN_H
+
+#include "Diagnostics.h"
+#include "xml/XmlDom.h"
+
+#include <android-base/macros.h>
+#include <functional>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace aapt {
+namespace xml {
+
+enum class XmlActionExecutorPolicy {
+ /**
+ * Actions on run if elements are matched, errors occur only when actions return false.
+ */
+ None,
+
+ /**
+ * The actions defined must match and run. If an element is found that does not match
+ * an action, an error occurs.
+ */
+ Whitelist,
+};
+
+/**
+ * Contains the actions to perform at this XML node. This is a recursive data structure that
+ * holds XmlNodeActions for child XML nodes.
+ */
+class XmlNodeAction {
+public:
+ using ActionFuncWithDiag = std::function<bool(Element*, SourcePathDiagnostics*)>;
+ using ActionFunc = std::function<bool(Element*)>;
+
+ /**
+ * Find or create a child XmlNodeAction that will be performed for the child element
+ * with the name `name`.
+ */
+ XmlNodeAction& operator[](const std::u16string& name) {
+ return mMap[name];
+ }
+
+ /**
+ * Add an action to be performed at this XmlNodeAction.
+ */
+ void action(ActionFunc f);
+ void action(ActionFuncWithDiag);
+
+private:
+ friend class XmlActionExecutor;
+
+ bool execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag, Element* el) const;
+
+ std::map<std::u16string, XmlNodeAction> mMap;
+ std::vector<ActionFuncWithDiag> mActions;
+};
+
+/**
+ * Allows the definition of actions to execute at specific XML elements defined by their
+ * hierarchy.
+ */
+class XmlActionExecutor {
+public:
+ XmlActionExecutor() = default;
+
+ /**
+ * Find or create a root XmlNodeAction that will be performed for the root XML element
+ * with the name `name`.
+ */
+ XmlNodeAction& operator[](const std::u16string& name) {
+ return mMap[name];
+ }
+
+ /**
+ * Execute the defined actions for this XmlResource.
+ * Returns true if all actions return true, otherwise returns false.
+ */
+ bool execute(XmlActionExecutorPolicy policy, IDiagnostics* diag, XmlResource* doc) const;
+
+private:
+ std::map<std::u16string, XmlNodeAction> mMap;
+
+ DISALLOW_COPY_AND_ASSIGN(XmlActionExecutor);
+};
+
+} // namespace xml
+} // namespace aapt
+
+#endif /* AAPT_XML_XMLPATTERN_H */
diff --git a/tools/aapt2/xml/XmlActionExecutor_test.cpp b/tools/aapt2/xml/XmlActionExecutor_test.cpp
new file mode 100644
index 000000000000..ebf287a251f2
--- /dev/null
+++ b/tools/aapt2/xml/XmlActionExecutor_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "test/Test.h"
+#include "xml/XmlActionExecutor.h"
+
+namespace aapt {
+namespace xml {
+
+TEST(XmlActionExecutorTest, BuildsAccessibleNestedPattern) {
+ XmlActionExecutor executor;
+ XmlNodeAction& manifestAction = executor[u"manifest"];
+ XmlNodeAction& applicationAction = manifestAction[u"application"];
+
+ Element* manifestEl = nullptr;
+ manifestAction.action([&](Element* manifest) -> bool {
+ manifestEl = manifest;
+ return true;
+ });
+
+ Element* applicationEl = nullptr;
+ applicationAction.action([&](Element* application) -> bool {
+ applicationEl = application;
+ return true;
+ });
+
+ std::unique_ptr<XmlResource> doc = test::buildXmlDom("<manifest><application /></manifest>");
+
+ StdErrDiagnostics diag;
+ ASSERT_TRUE(executor.execute(XmlActionExecutorPolicy::None, &diag, doc.get()));
+ ASSERT_NE(nullptr, manifestEl);
+ EXPECT_EQ(std::u16string(u"manifest"), manifestEl->name);
+
+ ASSERT_NE(nullptr, applicationEl);
+ EXPECT_EQ(std::u16string(u"application"), applicationEl->name);
+}
+
+TEST(XmlActionExecutorTest, FailsWhenUndefinedHierarchyExists) {
+ XmlActionExecutor executor;
+ executor[u"manifest"][u"application"];
+
+ std::unique_ptr<XmlResource> doc = test::buildXmlDom(
+ "<manifest><application /><activity /></manifest>");
+ StdErrDiagnostics diag;
+ ASSERT_FALSE(executor.execute(XmlActionExecutorPolicy::Whitelist, &diag, doc.get()));
+}
+
+} // namespace xml
+} // namespace aapt
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index f5938cfa37a5..265ebd1755e3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -423,21 +423,13 @@ public final class Path_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_offset(long nPath, float dx, float dy, long dst_path) {
+ /*package*/ static void native_offset(long nPath, float dx, float dy) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
}
- // could be null if the int is 0;
- Path_Delegate dstDelegate = sManager.getDelegate(dst_path);
-
- pathDelegate.offset(dx, dy, dstDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_offset(long nPath, float dx, float dy) {
- native_offset(nPath, dx, dy, 0);
+ pathDelegate.offset(dx, dy);
}
@LayoutlibDelegate
@@ -860,21 +852,14 @@ public final class Path_Delegate {
*
* @param dx The amount in the X direction to offset the entire path
* @param dy The amount in the Y direction to offset the entire path
- * @param dst The translated path is written here. If this is null, then
- * the original path is modified.
*/
- public void offset(float dx, float dy, Path_Delegate dst) {
+ public void offset(float dx, float dy) {
GeneralPath newPath = new GeneralPath();
PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
newPath.append(iterator, false /*connect*/);
-
- if (dst != null) {
- dst.mPath = newPath;
- } else {
- mPath = newPath;
- }
+ mPath = newPath;
}
/**
diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
index 01af669e39d3..381eb1f50973 100644
--- a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
@@ -15,8 +15,11 @@
*/
package android.view;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -64,4 +67,18 @@ public class Choreographer_Delegate {
thisChoreographer.doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
}
+
+ public static void dispose() {
+ try {
+ Field threadInstanceField = Choreographer.class.getDeclaredField("sThreadInstance");
+ threadInstanceField.setAccessible(true);
+ @SuppressWarnings("unchecked") ThreadLocal<Choreographer> threadInstance =
+ (ThreadLocal<Choreographer>) threadInstanceField.get(null);
+ threadInstance.remove();
+ } catch (ReflectiveOperationException e) {
+ assert false;
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Unable to clear Choreographer memory.", e, null);
+ }
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
index 30512aad4509..ea9a255e8561 100644
--- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
+++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
@@ -44,6 +44,11 @@ public class RectShadowPainter {
private static final float PERPENDICULAR_ANGLE = 90f;
public static void paintShadow(Outline viewOutline, float elevation, Canvas canvas) {
+ Rect outline = new Rect();
+ if (!viewOutline.getRect(outline)) {
+ throw new IllegalArgumentException("Outline is not a rect shadow");
+ }
+
float shadowSize = elevationToShadow(elevation);
int saved = modifyCanvas(canvas, shadowSize);
if (saved == -1) {
@@ -54,8 +59,7 @@ public class RectShadowPainter {
cornerPaint.setStyle(Style.FILL);
Paint edgePaint = new Paint(cornerPaint);
edgePaint.setAntiAlias(false);
- Rect outline = viewOutline.mRect;
- float radius = viewOutline.mRadius;
+ float radius = viewOutline.getRadius();
float outerArcRadius = radius + shadowSize;
int[] colors = {START_COLOR, START_COLOR, END_COLOR};
cornerPaint.setShader(new RadialGradient(0, 0, outerArcRadius, colors,
diff --git a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java b/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java
index 1465f5089599..24f788766cc9 100644
--- a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java
@@ -55,7 +55,7 @@ public class RenderNode_Delegate {
private String mName;
@LayoutlibDelegate
- /*package*/ static long nCreate(String name) {
+ /*package*/ static long nCreate(RenderNode thisRenderNode, String name) {
RenderNode_Delegate renderNodeDelegate = new RenderNode_Delegate();
renderNodeDelegate.mName = name;
return sManager.addNewDelegate(renderNodeDelegate);
diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
index 51d32e351eb8..23caaf85eb8e 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
@@ -64,7 +64,7 @@ public class ViewGroup_Delegate {
private static void drawShadow(ViewGroup parent, Canvas canvas, View child,
Outline outline) {
float elevation = getElevation(child, parent);
- if(outline.mRect != null) {
+ if(outline.mMode == Outline.MODE_ROUND_RECT && outline.mRect != null) {
RectShadowPainter.paintShadow(outline, elevation, canvas);
return;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index c8e3d03169e8..9e50ee898769 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -24,6 +24,7 @@ import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.ide.common.rendering.api.SessionParams;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.impl.RenderDrawable;
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
import com.android.layoutlib.bridge.util.DynamicIdMap;
@@ -408,7 +409,9 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
/**
* Starts a layout session by inflating and rendering it. The method returns a
* {@link RenderSession} on which further actions can be taken.
- *
+ * <p/>
+ * If {@link SessionParams} includes the {@link RenderParamsFlags#FLAG_DO_NOT_RENDER_ON_CREATE},
+ * this method will only inflate the layout but will NOT render it.
* @param params the {@link SessionParams} object with all the information necessary to create
* the scene.
* @return a new {@link RenderSession} object that contains the result of the layout.
@@ -424,7 +427,10 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
lastResult = scene.init(params.getTimeout());
if (lastResult.isSuccess()) {
lastResult = scene.inflate();
- if (lastResult.isSuccess()) {
+
+ boolean doNotRenderOnCreate = Boolean.TRUE.equals(
+ params.getFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE));
+ if (lastResult.isSuccess() && !doNotRenderOnCreate) {
lastResult = scene.render(true /*freshRender*/);
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 4161307aa8f3..2399b3a2345e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -110,13 +110,13 @@ import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_AP
public final class BridgeContext extends Context {
/** The map adds cookies to each view so that IDE can link xml tags to views. */
- private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
+ private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
/**
* In some cases, when inflating an xml, some objects are created. Then later, the objects are
* converted to views. This map stores the mapping from objects to cookies which can then be
* used to populate the mViewKeyMap.
*/
- private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>();
+ private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>();
private final BridgeAssetManager mAssets;
private Resources mSystemResources;
private final Object mProjectKey;
@@ -132,8 +132,7 @@ public final class BridgeContext extends Context {
private Resources.Theme mTheme;
- private final Map<Object, Map<String, String>> mDefaultPropMaps =
- new IdentityHashMap<Object, Map<String,String>>();
+ private final Map<Object, PropertiesMap> mDefaultPropMaps = new IdentityHashMap<>();
// maps for dynamically generated id representing style objects (StyleResourceValue)
@Nullable
@@ -142,13 +141,12 @@ public final class BridgeContext extends Context {
private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
// cache for TypedArray generated from StyleResourceValue object
- private Map<int[], Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>
- mTypedArrayCache;
+ private TypedArrayCache mTypedArrayCache;
private BridgeInflater mBridgeInflater;
private BridgeContentResolver mContentResolver;
- private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>();
+ private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>();
private SharedPreferences mSharedPreferences;
private ClassLoader mClassLoader;
private IBinder mBinder;
@@ -162,7 +160,7 @@ public final class BridgeContext extends Context {
* This a map from value to attribute name. Warning for missing references shouldn't be logged
* if value and attr name pair is the same as an entry in this map.
*/
- private static Map<String, String> RTL_ATTRS = new HashMap<String, String>(10);
+ private static Map<String, String> RTL_ATTRS = new HashMap<>(10);
static {
RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart");
@@ -325,11 +323,11 @@ public final class BridgeContext extends Context {
return mParserStack.get(mParserStack.size() - 2);
}
- public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
- Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid);
+ public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) {
+ Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resId);
boolean isFrameworkRes = true;
if (resourceInfo == null) {
- resourceInfo = mLayoutlibCallback.resolveResourceId(resid);
+ resourceInfo = mLayoutlibCallback.resolveResourceId(resId);
isFrameworkRes = false;
}
@@ -602,23 +600,20 @@ public final class BridgeContext extends Context {
@Override
public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
- // No style is specified here, so create the typed array based on the default theme
- // and the styles already applied to it. A null value of style indicates that the default
- // theme should be used.
- return createStyleBasedTypedArray(null, attrs);
+ return obtainStyledAttributes(0, attrs);
}
@Override
- public final BridgeTypedArray obtainStyledAttributes(int resid, int[] attrs)
+ public final BridgeTypedArray obtainStyledAttributes(int resId, int[] attrs)
throws Resources.NotFoundException {
StyleResourceValue style = null;
// get the StyleResourceValue based on the resId;
- if (resid != 0) {
- style = getStyleByDynamicId(resid);
+ if (resId != 0) {
+ style = getStyleByDynamicId(resId);
if (style == null) {
// In some cases, style may not be a dynamic id, so we do a full search.
- ResourceReference ref = resolveId(resid);
+ ResourceReference ref = resolveId(resId);
if (ref != null) {
style = mRenderResources.getStyle(ref.getName(), ref.isFramework());
}
@@ -629,41 +624,33 @@ public final class BridgeContext extends Context {
}
}
- // The map is from
- // attrs (int[]) -> context's current themes (List<StyleRV>) -> resid (int) -> typed array.
if (mTypedArrayCache == null) {
- mTypedArrayCache = new IdentityHashMap<int[],
- Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>();
+ mTypedArrayCache = new TypedArrayCache();
}
- // get the 2nd map
- Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>> map2 =
- mTypedArrayCache.get(attrs);
- if (map2 == null) {
- map2 = new HashMap<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>();
- mTypedArrayCache.put(attrs, map2);
- }
-
- // get the 3rd map
List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
- Map<Integer, BridgeTypedArray> map3 = map2.get(currentThemes);
- if (map3 == null) {
- map3 = new HashMap<Integer, BridgeTypedArray>();
- // Create a copy of the list before adding it to the map. This allows reusing the
- // existing list.
- currentThemes = new ArrayList<StyleResourceValue>(currentThemes);
- map2.put(currentThemes, map3);
- }
- // get the array from the 3rd map
- BridgeTypedArray ta = map3.get(resid);
+ Pair<BridgeTypedArray, PropertiesMap> typeArrayAndPropertiesPair =
+ mTypedArrayCache.get(attrs, currentThemes, resId);
- if (ta == null) {
- ta = createStyleBasedTypedArray(style, attrs);
- map3.put(resid, ta);
+ if (typeArrayAndPropertiesPair == null) {
+ typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs);
+ mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair);
}
-
- return ta;
+ // Add value to defaultPropsMap if needed
+ if (typeArrayAndPropertiesPair.getSecond() != null) {
+ Object key = getCurrentParser().getViewCookie();
+ if (key != null) {
+ PropertiesMap defaultPropMap = mDefaultPropMaps.get(key);
+ if (defaultPropMap == null) {
+ defaultPropMap = typeArrayAndPropertiesPair.getSecond();
+ mDefaultPropMaps.put(key, defaultPropMap);
+ } else {
+ defaultPropMap.putAll(typeArrayAndPropertiesPair.getSecond());
+ }
+ }
+ }
+ return typeArrayAndPropertiesPair.getFirst();
}
@Override
@@ -675,7 +662,7 @@ public final class BridgeContext extends Context {
public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
int defStyleAttr, int defStyleRes) {
- Map<String, String> defaultPropMap = null;
+ PropertiesMap defaultPropMap = null;
boolean isPlatformFile = true;
// Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
@@ -689,7 +676,7 @@ public final class BridgeContext extends Context {
if (key != null) {
defaultPropMap = mDefaultPropMaps.get(key);
if (defaultPropMap == null) {
- defaultPropMap = new HashMap<String, String>();
+ defaultPropMap = new PropertiesMap();
mDefaultPropMaps.put(key, defaultPropMap);
}
}
@@ -937,32 +924,33 @@ public final class BridgeContext extends Context {
*
* @see #obtainStyledAttributes(int, int[])
*/
- private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style,
- int[] attrs) throws Resources.NotFoundException {
-
+ private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
+ @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
- BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length,
- false);
+ BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
+ PropertiesMap defaultPropMap = new PropertiesMap();
// for each attribute, get its name so that we can search it in the style
- for (int i = 0 ; i < attrs.length ; i++) {
+ for (int i = 0; i < attrs.length; i++) {
Pair<String, Boolean> attribute = attributes.get(i);
if (attribute != null) {
// look for the value in the given style
ResourceValue resValue;
+ String attrName = attribute.getFirst();
if (style != null) {
- resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
+ resValue = mRenderResources.findItemInStyle(style, attrName,
attribute.getSecond());
} else {
- resValue = mRenderResources.findItemInTheme(attribute.getFirst(),
- attribute.getSecond());
+ resValue = mRenderResources.findItemInTheme(attrName, attribute.getSecond());
}
if (resValue != null) {
+ // Add it to defaultPropMap before resolving
+ defaultPropMap.put(attrName, resValue.getValue());
// resolve it to make sure there are no references left.
- ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
+ ta.bridgeSetValue(i, attrName, attribute.getSecond(),
mRenderResources.resolveResValue(resValue));
}
}
@@ -970,7 +958,7 @@ public final class BridgeContext extends Context {
ta.sealArray();
- return ta;
+ return Pair.of(ta, defaultPropMap);
}
/**
@@ -982,7 +970,7 @@ public final class BridgeContext extends Context {
* @return List of attribute information.
*/
private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
- List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length);
+ List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length);
// for each attribute, get its name so that we can search it in the style
for (int attr : attrs) {
@@ -1011,7 +999,7 @@ public final class BridgeContext extends Context {
* @return A (name, isFramework) pair describing the attribute if found. Returns null
* if nothing is found.
*/
- public Pair<String, Boolean> searchAttr(int attr) {
+ private Pair<String, Boolean> searchAttr(int attr) {
Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
if (info != null) {
return Pair.of(info.getSecond(), Boolean.TRUE);
@@ -1028,8 +1016,8 @@ public final class BridgeContext extends Context {
public int getDynamicIdByStyle(StyleResourceValue resValue) {
if (mDynamicIdToStyleMap == null) {
// create the maps.
- mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>();
- mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>();
+ mDynamicIdToStyleMap = new HashMap<>();
+ mStyleToDynamicIdMap = new HashMap<>();
}
// look for an existing id
@@ -1868,4 +1856,69 @@ public final class BridgeContext extends Context {
public boolean isCredentialProtectedStorage() {
return false;
}
+
+
+ /**
+ * The cached value depends on
+ * <ol>
+ * <li>{@code int[]}: the attributes for which TypedArray is created </li>
+ * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
+ * creation of the TypedArray</li>
+ * <li>{@code Integer}: the default style used at the time of creation</li>
+ * </ol>
+ *
+ * The class is created by using nested maps resolving one dependency at a time.
+ * <p/>
+ * The final value of the nested maps is a pair of the typed array and a map of properties
+ * that should be added to {@link #mDefaultPropMaps}, if needed.
+ */
+ private static class TypedArrayCache {
+
+ private Map<int[],
+ Map<List<StyleResourceValue>,
+ Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
+
+ public TypedArrayCache() {
+ mCache = new IdentityHashMap<>();
+ }
+
+ public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs,
+ List<StyleResourceValue> themes, int resId) {
+ Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
+ cacheFromThemes = mCache.get(attrs);
+ if (cacheFromThemes != null) {
+ Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
+ cacheFromThemes.get(themes);
+ if (cacheFromResId != null) {
+ return cacheFromResId.get(resId);
+ }
+ }
+ return null;
+ }
+
+ public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
+ Pair<BridgeTypedArray, PropertiesMap> value) {
+ Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
+ cacheFromThemes = mCache.get(attrs);
+ if (cacheFromThemes == null) {
+ cacheFromThemes = new HashMap<>();
+ mCache.put(attrs, cacheFromThemes);
+ }
+ Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
+ cacheFromThemes.get(themes);
+ if (cacheFromResId == null) {
+ cacheFromResId = new HashMap<>();
+ cacheFromThemes.put(themes, cacheFromResId);
+ }
+ cacheFromResId.put(resId, value);
+ }
+
+ }
+
+ /**
+ * An alias used for the value in {@code {@link #mDefaultPropMaps}}
+ */
+ private static class PropertiesMap extends HashMap<String, String> {
+ }
+
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
index bd17a2fe6ca2..051de9055042 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
@@ -53,6 +53,12 @@ public final class RenderParamsFlags {
*/
public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
new Key<Boolean>("xmlFileParser", Boolean.class);
+ /**
+ * To tell LayoutLib to not render when creating a new session. This allows controlling when the first
+ * layout rendering will happen.
+ */
+ public static final Key<Boolean> FLAG_DO_NOT_RENDER_ON_CREATE =
+ new Key<Boolean>("doNotRenderOnCreate", Boolean.class);
// Disallow instances.
private RenderParamsFlags() {}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 016825ae66e2..866b2480b828 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -267,6 +267,34 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
/**
+ * Renders the given view hierarchy to the passed canvas and returns the result of the render
+ * operation.
+ * @param canvas an optional canvas to render the views to. If null, only the measure and
+ * layout steps will be executed.
+ */
+ private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot,
+ @Nullable Canvas canvas, int width, int height) {
+ // measure again with the size we need
+ // This must always be done before the call to layout
+ measureView(viewRoot, null /*measuredView*/,
+ width, MeasureSpec.EXACTLY,
+ height, MeasureSpec.EXACTLY);
+
+ // now do the layout.
+ viewRoot.layout(0, 0, width, height);
+ handleScrolling(context, viewRoot);
+
+ if (canvas == null) {
+ return SUCCESS.createResult();
+ }
+
+ AttachInfo_Accessor.dispatchOnPreDraw(viewRoot);
+ viewRoot.draw(canvas);
+
+ return SUCCESS.createResult();
+ }
+
+ /**
* Renders the scene.
* <p>
* {@link #acquire(long)} must have been called before this.
@@ -367,24 +395,12 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
- // measure again with the size we need
- // This must always be done before the call to layout
- measureView(mViewRoot, null /*measuredView*/,
- mMeasuredScreenWidth, MeasureSpec.EXACTLY,
- mMeasuredScreenHeight, MeasureSpec.EXACTLY);
-
- // now do the layout.
- mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
-
- handleScrolling(mViewRoot);
-
+ Result renderResult = SUCCESS.createResult();
if (params.isLayoutOnly()) {
// delete the canvas and image to reset them on the next full rendering
mImage = null;
mCanvas = null;
} else {
- AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
-
// draw the views
// create the BufferedImage into which the layout will be rendered.
boolean newImage = false;
@@ -446,6 +462,9 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (mElapsedFrameTimeNanos >= 0) {
long initialTime = System_Delegate.nanoTime();
if (!mFirstFrameExecuted) {
+ // We need to run an initial draw call to initialize the animations
+ render(getContext(), mViewRoot, mCanvas, 0, 0);
+
// The first frame will initialize the animations
Choreographer_Delegate.doFrame(initialTime);
mFirstFrameExecuted = true;
@@ -453,14 +472,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// Second frame will move the animations
Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos);
}
- mViewRoot.draw(mCanvas);
+ renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth,
+ mMeasuredScreenHeight);
}
mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
false);
// success!
- return SUCCESS.createResult();
+ return renderResult;
} catch (Throwable e) {
// get the real cause of the exception.
Throwable t = e;
@@ -488,7 +508,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
* @return the measured width/height if measuredView is non-null, null otherwise.
*/
@SuppressWarnings("deprecation") // For the use of Pair
- private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
+ private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
int width, int widthMode, int height, int heightMode) {
int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
@@ -1061,8 +1081,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
* the component supports nested scrolling attempt that first, then use the unconsumed scroll
* part to scroll the content in the component.
*/
- private void handleScrolling(View view) {
- BridgeContext context = getContext();
+ private static void handleScrolling(BridgeContext context, View view) {
int scrollPosX = context.getScrollXPos(view);
int scrollPosY = context.getScrollYPos(view);
if (scrollPosX != 0 || scrollPosY != 0) {
@@ -1080,7 +1099,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
if (scrollPosX != 0 || scrollPosY != 0) {
- view.scrollBy(scrollPosX, scrollPosY);
+ view.scrollTo(scrollPosX, scrollPosY);
}
}
@@ -1090,7 +1109,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
- handleScrolling(child);
+ handleScrolling(context, child);
}
}
@@ -1434,6 +1453,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (createdLooper) {
Bridge.cleanupThread();
+ Choreographer_Delegate.dispose();
}
}
}
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index d8ead233b4ec..0e788e0c8264 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
index 65d1dc5b1edb..bad296bf4a66 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
index 2da2cb983a6c..adb58a322abb 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
@@ -197,6 +197,14 @@
android:inputType="numberPassword"
android:text="numeric password" />
+ <ToggleButton
+ android:id="@+id/toggleButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/editText4"
+ android:layout_toEndOf="@id/editText4"
+ android:text="New ToggleButton" />
+
<EditText
android:id="@id/editText5"
android:layout_width="wrap_content"
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
index a5ebc2e20847..a07498cd07b1 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
@@ -2,8 +2,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:scrollX="10px"
- android:scrollY="30px">
+ android:scrollX="30px"
+ android:scrollY="90px">
<LinearLayout
android:layout_width="60dp"
android:layout_height="60dp"
@@ -29,8 +29,8 @@
android:layout_width="200dp"
android:layout_height="400dp"
android:orientation="vertical"
- android:scrollX="-30px"
- android:scrollY="150px">
+ android:scrollX="-90px"
+ android:scrollY="450px">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="60dp"
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 09dd5f078b9a..8f570aee96b7 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -30,8 +30,9 @@ import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.io.FolderWrapper;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.RenderAction;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback;
import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
@@ -41,8 +42,12 @@ import com.android.resources.ResourceType;
import com.android.utils.ILogger;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -55,9 +60,12 @@ import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
+import com.google.android.collect.Lists;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -104,6 +112,21 @@ public class Main {
private static ILogger sLogger;
private static Bridge sBridge;
+ /** List of log messages generated by a render call. It can be used to find specific errors */
+ private static ArrayList<String> sRenderMessages = Lists.newArrayList();
+
+ @Rule
+ public static TestWatcher sRenderMessageWatcher = new TestWatcher() {
+ @Override
+ protected void succeeded(Description description) {
+ // We only check error messages if the rest of the test case was successful.
+ if (!sRenderMessages.isEmpty()) {
+ fail(description.getMethodName() + " render error message: " + sRenderMessages.get
+ (0));
+ }
+ }
+ };
+
static {
// Test that System Properties are properly set.
PLATFORM_DIR = getPlatformDir();
@@ -278,6 +301,11 @@ public class Main {
ConfigGenerator.getEnumMap(attrs), getLayoutLog());
}
+ @Before
+ public void beforeTestCase() {
+ sRenderMessages.clear();
+ }
+
/** Test activity.xml */
@Test
public void testActivity() throws ClassNotFoundException {
@@ -288,6 +316,9 @@ public class Main {
@Test
public void testAllWidgets() throws ClassNotFoundException {
renderAndVerify("allwidgets.xml", "allwidgets.png");
+
+ // We expect fidelity warnings for Path.isConvex. Fail for anything else.
+ sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
}
@Test
@@ -298,6 +329,9 @@ public class Main {
@Test
public void testAllWidgetsTablet() throws ClassNotFoundException {
renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012);
+
+ // We expect fidelity warnings for Path.isConvex. Fail for anything else.
+ sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
}
private static void gc() {
@@ -564,7 +598,7 @@ public class Main {
sFrameworkRepo.getConfiguredResources(config),
themeName, isProjectTheme);
- return new SessionParams(
+ SessionParams sessionParams = new SessionParams(
layoutParser,
renderingMode,
null /*used for caching*/,
@@ -574,6 +608,8 @@ public class Main {
0,
targetSdk,
getLayoutLog());
+ sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true);
+ return sessionParams;
}
private static LayoutLog getLayoutLog() {
@@ -646,6 +682,6 @@ public class Main {
}
private static void failWithMsg(@NonNull String msgFormat, Object... args) {
- fail(args == null ? "" : String.format(msgFormat, args));
+ sRenderMessages.add(args == null ? msgFormat : String.format(msgFormat, args));
}
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 1c7a308746b0..6ca4393a232a 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -149,9 +149,6 @@ interface IWifiManager
void setAllowScansWithTraffic(int enabled);
int getAllowScansWithTraffic();
- void setHalBasedAutojoinOffload(int enabled);
- int getHalBasedAutojoinOffload();
-
boolean enableAutoJoinWhenAssociated(boolean enabled);
boolean getEnableAutoJoinWhenAssociated();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 9e15d6009e72..394934f59f51 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -719,7 +719,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* Get CA certificates.
*/
@Nullable public X509Certificate[] getCaCertificates() {
- if (mCaCerts != null || mCaCerts.length > 0) {
+ if (mCaCerts != null && mCaCerts.length > 0) {
return mCaCerts;
} else {
return null;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8c1fbc3a6def..6653a8dd6e07 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -28,7 +28,6 @@ import android.net.NetworkRequest;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -43,7 +42,6 @@ import com.android.internal.util.Protocol;
import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -2721,27 +2719,4 @@ public class WifiManager {
throw e.rethrowFromSystemServer();
}
}
- /**
- * Set setting for enabling autojoin Offload thru Wifi HAL layer
- * @hide
- */
- public void setHalBasedAutojoinOffload(int enabled) {
- try {
- mService.setHalBasedAutojoinOffload(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get setting for enabling autojoin Offload thru Wifi HAL layer
- * @hide
- */
- public int getHalBasedAutojoinOffload() {
- try {
- return mService.getHalBasedAutojoinOffload();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
}